Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions content/en/continuous-deployment/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
## Additional Armory products

### Kubernetes Operators for installation
{{% alert color="warning" title="Important" %}}
[Armory Operator]({{< ref "armory-operator" >}}) has been deprecated and will is considered EOL. Please migrate to the [Kustomize]({{< ref "armory-operator-to-kustomize-migration" >}}) method of deployment.

Check warning on line 23 in content/en/continuous-deployment/_index.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/_index.md#L23

[Google.Will] Avoid using ' will '.
Raw output
{"message": "[Google.Will] Avoid using ' will '.", "location": {"path": "content/en/continuous-deployment/_index.md", "range": {"start": {"line": 23, "column": 73}}}, "severity": "WARNING"}
{{% /alert %}}

The [Armory Operator]({{< ref "armory-operator" >}}) is a Kubernetes Operator that helps you configure, deploy, and update Armory Continuous Deployment on Kubernetes clusters.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

{{< include "armory-license.md" >}}

{{% alert color="warning" title="Important" %}}
[Armory Operator]({{< ref "armory-operator" >}}) has been deprecated and will is considered EOL. Please migrate to the [Kustomize]({{< ref "armory-operator-to-kustomize-migration" >}}) method of deployment.

Check warning on line 15 in content/en/continuous-deployment/installation/armory-operator/_index.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/installation/armory-operator/_index.md#L15

[Google.Will] Avoid using ' will '.
Raw output
{"message": "[Google.Will] Avoid using ' will '.", "location": {"path": "content/en/continuous-deployment/installation/armory-operator/_index.md", "range": {"start": {"line": 15, "column": 73}}}, "severity": "WARNING"}
{{% /alert %}}


## What are Kubernetes Operators for Spinnaker?

From the Kubernetes [Operator pattern docs](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/): "Operators are software extensions to Kubernetes that make use of custom resources to manage applications and their components." In other words, an Operator is a Kubernetes controller that manages a specific application using a custom resource. Both the proprietary Armory Operator and the open source [Spinnaker Operator for Kubernetes](https://github.com/armory/spinnaker-operator) are custom Kubernetes Operators that you can install in your cluster.
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
---
title: Migrating Armory CD from Operator to Kustomize Deployment
linkTitle: Migrating from Operator to Kustomize Deployment
aliases: []
description: >
Learn how to migrate Armory CD from Operator to Kustomize Deployment.
---

## Migrating Armory CD from Operator to Kustomize Deployment

Check warning on line 9 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L9

[Google.Headings] 'Migrating Armory CD from Operator to Kustomize Deployment' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Migrating Armory CD from Operator to Kustomize Deployment' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 9, "column": 4}}}, "severity": "WARNING"}

### Introduction

This document provides step-by-step instructions for migrating your Spinnaker installation from using the Operator deployment method to a native Kubernetes deployment using Kustomize. This approach gives you more direct control over your Spinnaker resources and removes the dependency on the Operator.

{{% alert color="warning" title="Important" %}}
Please thoroughly test this migration in a non-production environment before deploying to production.
{{% /alert %}}


#### Prerequisites

- Kubectl command-line tool installed and configured to access your cluster
- Basic understanding of Kubernetes resources (deployments, services, configmaps)
- Access to the current Spinnaker namespace

#### Migration Process Overview

Check warning on line 26 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L26

[Google.Headings] 'Migration Process Overview' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Migration Process Overview' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 26, "column": 6}}}, "severity": "WARNING"}

1. Download current configuration files and Kubernetes resources
2. Set up Kustomize structure for native deployment
3. Remove Operator ownership from services
4. Scale down the Operator
5. Deploy using Kustomize
6. Validate the deployment
7. Remove Operator and CRDs (after confirming stability)

##### Step 1: Download Current Configuration

Check warning on line 36 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L36

[Google.Headings] 'Step 1: Download Current Configuration' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 1: Download Current Configuration' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 36, "column": 7}}}, "severity": "WARNING"}

The script provided below will download:

Check warning on line 38 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L38

[Google.Will] Avoid using ' will '.
Raw output
{"message": "[Google.Will] Avoid using ' will '.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 38, "column": 26}}}, "severity": "WARNING"}
- All configuration files located in /opt/spinnaker/config from each service
- All deployment, service, and statefulset YAML files for each service


###### How to Use the Download Script

Check warning on line 43 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L43

[Google.Headings] 'How to Use the Download Script' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'How to Use the Download Script' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 43, "column": 8}}}, "severity": "WARNING"}

1. Save the script at the bottom of this document to a file named `download_spinnaker_configs.sh`
2. Make the script executable:
`chmod +x download_spinnaker_configs.sh`
3. Run the script with your Spinnaker namespace:
`./download_spinnaker_configs.sh your-spinnaker-namespace`
4. The script will create an operator-migration directory containing all needed files

Check warning on line 50 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L50

[Google.Will] Avoid using ' will '.
Raw output
{"message": "[Google.Will] Avoid using ' will '.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 50, "column": 14}}}, "severity": "WARNING"}

###### What Gets Downloaded

Check warning on line 52 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L52

[Google.Headings] 'What Gets Downloaded' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'What Gets Downloaded' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 52, "column": 8}}}, "severity": "WARNING"}

- **Deployments:** YAML files for each service deployment
- **Services:** YAML files for all Spinnaker services
- **StatefulSets:** YAML files for any statefulsets (like front50)
- **Configuration Files:** All files from /opt/spinnaker/config in each pod

##### Step 2: Set Up Kustomize Structure

Check warning on line 59 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L59

[Google.Headings] 'Step 2: Set Up Kustomize Structure' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 2: Set Up Kustomize Structure' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 59, "column": 7}}}, "severity": "WARNING"}

Create a Kustomize directory structure for your Spinnaker deployment:
1. Move the downloaded deployments and services to their respective directories
2. Create configmaps from the downloaded configuration files
3. Set up the kustomization.yaml files

{{% alert color="warning" title="Tip" %}}
You can use the GitHub - spinnaker/spinnaker-kustomize: Spinnaker installation via kustomize as a reference for Kustomize structure
{{% /alert %}}

##### Step 3: Remove Operator Ownership from Services

Check warning on line 70 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L70

[Google.Headings] 'Step 3: Remove Operator Ownership from Services' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 3: Remove Operator Ownership from Services' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 70, "column": 7}}}, "severity": "WARNING"}

This step detaches the Operator's control while keeping services running.
1. Identify resources owned by the Operator:
`kubectl get all -n your-spinnaker-namespace -o json | jq '.items[] | select(.metadata.ownerReferences[]? | .apiVersion=="spinnaker.armory.io/v1alpha2" and .kind=="SpinnakerService") | {name: .metadata.name, kind: .kind}'`
2. Remove ownership references using patch commands:
`kubectl patch deployment spin-deck -n your-spinnaker-namespace --type json -p='[{"op": "remove", "path": "/metadata/ownerReferences"}]'`
3. Repeat for all resources with Operator ownership
{{% alert color="warning" title="Note" %}}
This breaks the connection between the Operator and services but keeps everything running
{{% /alert %}}

##### Step 4: Verify Ownership Removal

Check warning on line 82 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L82

[Google.Headings] 'Step 4: Verify Ownership Removal' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 4: Verify Ownership Removal' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 82, "column": 7}}}, "severity": "WARNING"}

Confirm that no resources are still owned by the Operator:
`kubectl get all -n your-spinnaker-namespace -o json | jq '.items[] | select(.metadata.ownerReferences[]? | .apiVersion=="spinnaker.armory.io/v1alpha2" and .kind=="SpinnakerService") | {name: .metadata.name, kind: .kind}'`
The command should return empty if all ownership references have been removed.

##### Step 5: Extra Precautions Before Deployment

Check warning on line 88 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L88

[Google.Headings] 'Step 5: Extra Precautions Before Deployment' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 5: Extra Precautions Before Deployment' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 88, "column": 7}}}, "severity": "WARNING"}
Compare current resources with your Kustomize configurations:
`kubectl diff -f <(kustomize build ./overlays/prod)`

Review the differences carefully. Look for:
- Immutable field changes (might require special handling)
- Configuration changes that could affect service behavior
- Missing resources that should be included

###### Perform a Dry Run

Check warning on line 97 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L97

[Google.Headings] 'Perform a Dry Run' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Perform a Dry Run' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 97, "column": 8}}}, "severity": "WARNING"}

Test your deployment without actually applying changes:
`kubectl apply --dry-run=client -f <(kustomize build ./overlays/prod)`

##### Step 6: Scale Down the Operator

Check warning on line 102 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L102

[Google.Headings] 'Step 6: Scale Down the Operator' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 6: Scale Down the Operator' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 102, "column": 7}}}, "severity": "WARNING"}
Prevent the Operator from interfering with your deployment:
`kubectl scale deployment spinnaker-operator -n your-spinnaker-namespace --replicas=0`

##### Step 7: Deploy Using Kustomize

Check warning on line 106 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L106

[Google.Headings] 'Step 7: Deploy Using Kustomize' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 7: Deploy Using Kustomize' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 106, "column": 7}}}, "severity": "WARNING"}

Apply your Kustomize configurations:

`kubectl apply -f <(kustomize build ./overlays/prod)`

##### Step 8: Validate and Monitor

Check warning on line 112 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L112

[Google.Headings] 'Step 8: Validate and Monitor' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 8: Validate and Monitor' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 112, "column": 7}}}, "severity": "WARNING"}
1. Check that all pods are running:
`kubectl get pods -n your-spinnaker-namespace`
2. Verify Spinnaker services are accessible:
- Access the Spinnaker UI
- Test a simple pipeline
- Check integrations are working
3. Monitor the environment for stability over the next few days

##### Step 9: Remove Operator and CRDs

Check warning on line 121 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L121

[Google.Headings] 'Step 9: Remove Operator and CRDs' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Step 9: Remove Operator and CRDs' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 121, "column": 7}}}, "severity": "WARNING"}

Once stability is confirmed (at least 24 hours later):
1. Remove the Operator CRDs:
`kubectl delete crd spinnakerservices.spinnaker.armory.io`
2. Remove the Operator deployment if still present:
`kubectl delete deployment spinnaker-operator -n your-spinnaker-namespace`


##### Rollback Plan

Check warning on line 130 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L130

[Google.Headings] 'Rollback Plan' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Rollback Plan' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 130, "column": 7}}}, "severity": "WARNING"}
If issues arise during migration:
1. Scale up the Operator:
`kubectl scale deployment spinnaker-operator -n your-spinnaker-namespace --replicas=1`
2. Reapply the previous SpinnakerService resource:
`kubectl apply -f original-spinnakerservice.yaml`
3. Allow the Operator to reconcile and restore the previous state

#### Download Script

Check warning on line 138 in content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md#L138

[Google.Headings] 'Download Script' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Download Script' should use sentence-style capitalization.", "location": {"path": "content/en/continuous-deployment/spinnaker-user-guides/armory-operator-to-kustomize-migration.md", "range": {"start": {"line": 138, "column": 6}}}, "severity": "WARNING"}
```bash
#!/bin/bash

# Script to download ONLY files from /opt/spinnaker/config in Spinnaker pods

set -e

if [ -z "$1" ]; then
echo "Please provide a namespace"
echo "Usage: $0 <namespace>"
exit 1
fi

NAMESPACE=$1
OUTPUT_DIR="operator-migration"

echo "Creating output directory: $OUTPUT_DIR"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"

# 1. First download deployments and services
echo "Downloading Kubernetes deployments and services..."

# Download Deployments
echo "Downloading deployments..."
mkdir -p "$OUTPUT_DIR/deployments"
kubectl get deployments -n "$NAMESPACE" -o name | while read -r deployment; do
deployment_name=$(echo "$deployment" | cut -d/ -f2)
echo "Downloading deployment: $deployment_name"
kubectl get deployment "$deployment_name" -n "$NAMESPACE" -o yaml > "$OUTPUT_DIR/deployments/$deployment_name.yaml"
done

# Download Services
echo "Downloading services..."
mkdir -p "$OUTPUT_DIR/services"
kubectl get services -n "$NAMESPACE" -o name | while read -r service; do
service_name=$(echo "$service" | cut -d/ -f2)
echo "Downloading service: $service_name"
kubectl get service "$service_name" -n "$NAMESPACE" -o yaml > "$OUTPUT_DIR/services/$service_name.yaml"
done

# Download StatefulSets if any
echo "Checking for statefulsets..."
if kubectl get statefulsets -n "$NAMESPACE" 2>/dev/null | grep -q .; then
mkdir -p "$OUTPUT_DIR/statefulsets"
kubectl get statefulsets -n "$NAMESPACE" -o name | while read -r statefulset; do
statefulset_name=$(echo "$statefulset" | cut -d/ -f2)
echo "Downloading statefulset: $statefulset_name"
kubectl get statefulset "$statefulset_name" -n "$NAMESPACE" -o yaml > "$OUTPUT_DIR/statefulsets/$statefulset_name.yaml"
done
fi

# 2. Now download files from /opt/spinnaker/config
echo "Downloading files ONLY from /opt/spinnaker/config..."

# Get all pods
PODS=$(kubectl get pods -n "$NAMESPACE" -o name | cut -d/ -f2)
for POD in $PODS; do
SERVICE=$(echo "$POD" | sed -E 's/([a-z-]+)-[0-9a-z-]+.*/\1/')

echo "Processing pod: $POD (service: $SERVICE)"
mkdir -p "$OUTPUT_DIR/$SERVICE"

# Check ONLY for /opt/spinnaker/config
if kubectl exec -n "$NAMESPACE" "$POD" -- ls -la /opt/spinnaker/config &>/dev/null; then
echo "Found /opt/spinnaker/config directory in $POD"

# List all files first
CONFIG_FILES=$(kubectl exec -n "$NAMESPACE" "$POD" -- find /opt/spinnaker/config -type f 2>/dev/null)
if [ -z "$CONFIG_FILES" ]; then
echo "No files found in /opt/spinnaker/config for $POD"
continue
fi

echo "Found $(echo "$CONFIG_FILES" | wc -l | tr -d ' ') files in /opt/spinnaker/config for $POD"

# Download each file
for FILE in $CONFIG_FILES; do
FILENAME=$(basename "$FILE")
echo "Downloading $FILENAME from $POD"

FILE_CONTENT=$(kubectl exec -n "$NAMESPACE" "$POD" -- cat "$FILE" 2>/dev/null)
if [ $? -eq 0 ] && [ -n "$FILE_CONTENT" ]; then
echo "$FILE_CONTENT" > "$OUTPUT_DIR/$SERVICE/$FILENAME"
echo "Saved $FILENAME to $OUTPUT_DIR/$SERVICE/$FILENAME"
else
echo "Failed to download $FILENAME or file is empty"
fi
done

# Check if we downloaded any files
if [ -z "$(ls -A "$OUTPUT_DIR/$SERVICE" 2>/dev/null)" ]; then
echo "No files were successfully downloaded from $POD"
else
echo "Successfully downloaded $(ls -1 "$OUTPUT_DIR/$SERVICE" | wc -l | tr -d ' ') files from $POD"
fi
else
echo "No /opt/spinnaker/config directory found in $POD"
fi
done

echo "======================================"
echo "Download completed. Files saved to: $OUTPUT_DIR"
echo "Summary of downloaded files by service:"

# Generate summary
for DIR in $(find "$OUTPUT_DIR" -mindepth 1 -maxdepth 1 -type d | sort); do
SERVICE=$(basename "$DIR")
FILE_COUNT=$(find "$DIR" -type f | wc -l)

echo "- $SERVICE: $FILE_COUNT files"
if [ "$FILE_COUNT" -gt 0 ]; then
ls -1 "$DIR" | sort | while read -r file; do
echo " - $file"
done
fi
done

echo "Script execution complete!"

```
### Conclusion
By following these steps, you'll successfully migrate from the Spinnaker Operator to a native Kubernetes deployment using Kustomize. This approach gives you more direct control over your Spinnaker resources and eliminates dependency on the Operator.
If you encounter any issues during the migration process, please submit a support ticket for assistance.
Loading