diff --git a/pkg/fixtures/validatetemplate.go b/pkg/fixtures/validatetemplate.go index 12862562..ab10b189 100644 --- a/pkg/fixtures/validatetemplate.go +++ b/pkg/fixtures/validatetemplate.go @@ -5,30 +5,25 @@ import ( "os" "regexp" "strings" + + "github.com/google/go-cmp/cmp" ) func ValidateContentAgainstFixture(generatedContent []byte, fixturePath string) error { + got := generatedContent // Read the fixture content - fixtureContent, err := os.ReadFile(fixturePath) + want, err := os.ReadFile(fixturePath) if err != nil { return fmt.Errorf("failed to read fixture: %w", err) } - if normalizeWhitespace(fixtureContent) != normalizeWhitespace(generatedContent) { - genWords := strings.Split(normalizeWhitespace(generatedContent), " ") - fixtureWords := strings.Split(normalizeWhitespace(fixtureContent), " ") - differingWords := []string{} - for i, word := range genWords { - if i < len(fixtureWords) && word != fixtureWords[i] { - differingWords = append(differingWords, fmt.Sprintf("'%s' != '%s'", word, fixtureWords[i])) - if len(differingWords) == 1 { - fmt.Println("Generated Word | Fixture Word") - } - fmt.Printf("'%s' != '%s'\n", word, fixtureWords[i]) - } + if normalizeWhitespace(want) != normalizeWhitespace(got) { + if diff := cmp.Diff(string(want), string(got)); diff != "" { + fmt.Println("Diff for file ", fixturePath, " (-want +got)") + fmt.Printf(diff) + return fmt.Errorf("generated content does not match fixture for file %s, check above for rich diff", fixturePath) } - return fmt.Errorf("generated content does not match fixture for file %s: %s", fixturePath, strings.Join(differingWords, ", ")) } return nil diff --git a/pkg/fixtures/workflows/github/helm/.github/workflows/azure-kubernetes-service-helm.yml b/pkg/fixtures/workflows/github/helm/.github/workflows/azure-kubernetes-service-helm.yml index ee8eea28..3b3f14a2 100644 --- a/pkg/fixtures/workflows/github/helm/.github/workflows/azure-kubernetes-service-helm.yml +++ b/pkg/fixtures/workflows/github/helm/.github/workflows/azure-kubernetes-service-helm.yml @@ -54,6 +54,7 @@ env: CHART_OVERRIDE_PATH: testOverridePath CHART_OVERRIDES: replicas:2 NAMESPACE: default + ENABLENAMESPACECREATION: false jobs: buildImage: @@ -112,6 +113,17 @@ jobs: admin: "false" use-kubelogin: "true" + # Create Namespace + - name: Create Namespace + if: ${{ env.ENABLENAMESPACECREATION == 'true' }} + run: | + kubectl get namespace ${{ env.NAMESPACE }} || kubectl create namespace ${{ env.NAMESPACE }} + + # Validate Namespace exists + - name: Validate Namespace Exists + run: | + kubectl get namespace ${{ env.NAMESPACE }} + # Checks if the AKS cluster is private - name: Is private cluster id: isPrivate @@ -122,9 +134,9 @@ jobs: # Deploys application - name: Deploy application on private cluster - if: steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' + if: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' }} run: | - command_id=$(az aks command invoke --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command "helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} --create-namespace --timeout 240s" --file . --query id -o tsv) + command_id=$(az aks command invoke --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command "helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} --timeout 240s" --file . --query id -o tsv) result=$(az aks command result --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command-id $command_id) echo "Helm upgrade result: $result" exitCode=$(az aks command result --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command-id $command_id --query exitCode -o tsv) @@ -134,11 +146,6 @@ jobs: fi - name: Deploy application on public cluster - if: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' && env.CLUSTER_RESOURCE_TYPE != 'Microsoft.ContainerService/fleets' }} - run: | - helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} --create-namespace - - - name: Deploy application on fleet hub cluster - if: ${{ env.CLUSTER_RESOURCE_TYPE == 'Microsoft.ContainerService/fleets' }} + if: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' }} run: | - helm upgrade -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} + helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} diff --git a/pkg/fixtures/workflows/github/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml b/pkg/fixtures/workflows/github/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml index 66799304..af6f37ad 100644 --- a/pkg/fixtures/workflows/github/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml +++ b/pkg/fixtures/workflows/github/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml @@ -53,6 +53,7 @@ env: DOCKER_FILE: ./Dockerfile BUILD_CONTEXT_PATH: test NAMESPACE: default + ENABLENAMESPACECREATION: false jobs: buildImage: @@ -111,6 +112,17 @@ jobs: use-kubelogin: 'true' resource-type: ${{ env.CLUSTER_RESOURCE_TYPE }} + # Create Namespace + - name: Create Namespace + if: ${{ env.ENABLENAMESPACECREATION == 'true' }} + run: | + kubectl get namespace ${{ env.NAMESPACE }} || kubectl create namespace ${{ env.NAMESPACE }} + + # Validate Namespace exists + - name: Validate Namespace Exists + run: | + kubectl get namespace ${{ env.NAMESPACE }} + # Runs Kustomize to create manifest files - name: Bake deployment uses: azure/k8s-bake@v2 diff --git a/pkg/handlers/template.go b/pkg/handlers/template.go index 77863b42..cf0472d4 100644 --- a/pkg/handlers/template.go +++ b/pkg/handlers/template.go @@ -62,7 +62,7 @@ func GetTemplate(name, version, dest string, templateWriter templatewriter.Templ func (t *Template) Generate() error { if err := t.validate(); err != nil { log.Printf("template validation failed: %s", err.Error()) - return err + return fmt.Errorf("generating template: %w", err) } if err := t.Config.ApplyDefaultVariablesForVersion(t.version); err != nil { diff --git a/template/deployments/helm/draft.yaml b/template/deployments/helm/draft.yaml index 4265fedc..18e16004 100644 --- a/template/deployments/helm/draft.yaml +++ b/template/deployments/helm/draft.yaml @@ -229,4 +229,4 @@ variables: disablePrompt: true value: "secret-ref" description: "the name of the kubernetes secret reference" - versions: ">=0.0.1" \ No newline at end of file + versions: ">=0.0.1" diff --git a/template/deployments/kustomize/base/namespace.yaml b/template/deployments/kustomize/base/namespace.yaml deleted file mode 100644 index d88099a4..00000000 --- a/template/deployments/kustomize/base/namespace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Namespace -apiVersion: v1 -metadata: - name: {{ .Config.GetVariableValue "NAMESPACE" }} - labels: - kubernetes.azure.com/generator: {{ .Config.GetVariableValue "GENERATORLABEL" }} \ No newline at end of file diff --git a/template/deployments/kustomize/draft.yaml b/template/deployments/kustomize/draft.yaml index 8908041f..e00a15ad 100644 --- a/template/deployments/kustomize/draft.yaml +++ b/template/deployments/kustomize/draft.yaml @@ -229,4 +229,4 @@ variables: value: "true" condition: "equals" description: "the name of the service account to use with workload identity" - versions: ">=0.0.1" \ No newline at end of file + versions: ">=0.0.1" diff --git a/template/deployments/manifests/draft.yaml b/template/deployments/manifests/draft.yaml index d2104ed5..071291c7 100644 --- a/template/deployments/manifests/draft.yaml +++ b/template/deployments/manifests/draft.yaml @@ -229,4 +229,4 @@ variables: disablePrompt: true value: "secret-ref" description: "the name of the kubernetes secret reference" - versions: ">=0.0.1" \ No newline at end of file + versions: ">=0.0.1" diff --git a/template/workflows/helm/.github/workflows/azure-kubernetes-service-helm.yml b/template/workflows/helm/.github/workflows/azure-kubernetes-service-helm.yml index 48e9affc..ba72ebef 100644 --- a/template/workflows/helm/.github/workflows/azure-kubernetes-service-helm.yml +++ b/template/workflows/helm/.github/workflows/azure-kubernetes-service-helm.yml @@ -54,6 +54,7 @@ env: CHART_OVERRIDE_PATH: {{ .Config.GetVariableValue "CHARTOVERRIDEPATH" }} CHART_OVERRIDES: {{ .Config.GetVariableValue "CHARTOVERRIDES" }} NAMESPACE: {{ .Config.GetVariableValue "NAMESPACE" }} + ENABLENAMESPACECREATION: {{ .Config.GetVariableValue "ENABLENAMESPACECREATION" }} {{` jobs: buildImage: @@ -112,6 +113,17 @@ jobs: admin: "false" use-kubelogin: "true" + # Create Namespace + - name: Create Namespace + if: ${{ env.ENABLENAMESPACECREATION == 'true' }} + run: | + kubectl get namespace ${{ env.NAMESPACE }} || kubectl create namespace ${{ env.NAMESPACE }} + + # Validate Namespace exists + - name: Validate Namespace Exists + run: | + kubectl get namespace ${{ env.NAMESPACE }} + # Checks if the AKS cluster is private - name: Is private cluster id: isPrivate @@ -122,9 +134,9 @@ jobs: # Deploys application - name: Deploy application on private cluster - if: steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' + if: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' }} run: | - command_id=$(az aks command invoke --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command "helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} --create-namespace --timeout 240s" --file . --query id -o tsv) + command_id=$(az aks command invoke --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command "helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} --timeout 240s" --file . --query id -o tsv) result=$(az aks command result --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command-id $command_id) echo "Helm upgrade result: $result" exitCode=$(az aks command result --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command-id $command_id --query exitCode -o tsv) @@ -134,12 +146,7 @@ jobs: fi - name: Deploy application on public cluster - if: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' && env.CLUSTER_RESOURCE_TYPE != 'Microsoft.ContainerService/fleets' }} - run: | - helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} --create-namespace - - - name: Deploy application on fleet hub cluster - if: ${{ env.CLUSTER_RESOURCE_TYPE == 'Microsoft.ContainerService/fleets' }} + if: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' }} run: | - helm upgrade -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} + helm upgrade --wait -i -f ${{ env.CHART_OVERRIDE_PATH }} --set ${{ env.CHART_OVERRIDES }} --set image.tag=${{ github.sha }} automated-deployment ${{ env.CHART_PATH }} --namespace ${{ env.NAMESPACE }} `}} diff --git a/template/workflows/helm/draft.yaml b/template/workflows/helm/draft.yaml index 378a3b11..98787493 100644 --- a/template/workflows/helm/draft.yaml +++ b/template/workflows/helm/draft.yaml @@ -86,3 +86,11 @@ variables: value: "default" description: "the Kubernetes namespace" versions: ">=0.0.1" + - name: "ENABLENAMESPACECREATION" + type: "bool" + kind: "flag" + default: + disablePrompt: true + value: "false" + description: "enable creation of target namespace if it does not exist" + versions: ">=0.0.1" diff --git a/template/workflows/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml b/template/workflows/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml index 3d05ecb7..57eb6db5 100644 --- a/template/workflows/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml +++ b/template/workflows/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml @@ -53,6 +53,7 @@ env: DOCKER_FILE: {{ .Config.GetVariableValue "DOCKERFILE" }} BUILD_CONTEXT_PATH: {{ .Config.GetVariableValue "BUILDCONTEXTPATH" }} NAMESPACE: {{ .Config.GetVariableValue "NAMESPACE" }} + ENABLENAMESPACECREATION: {{ .Config.GetVariableValue "ENABLENAMESPACECREATION" }} {{` jobs: buildImage: @@ -111,6 +112,17 @@ jobs: use-kubelogin: 'true' resource-type: ${{ env.CLUSTER_RESOURCE_TYPE }} + # Create Namespace + - name: Create Namespace + if: ${{ env.ENABLENAMESPACECREATION == 'true' }} + run: | + kubectl get namespace ${{ env.NAMESPACE }} || kubectl create namespace ${{ env.NAMESPACE }} + + # Validate Namespace exists + - name: Validate Namespace Exists + run: | + kubectl get namespace ${{ env.NAMESPACE }} + # Runs Kustomize to create manifest files - name: Bake deployment uses: azure/k8s-bake@v2 diff --git a/template/workflows/kustomize/draft.yaml b/template/workflows/kustomize/draft.yaml index 378da838..47bda64b 100644 --- a/template/workflows/kustomize/draft.yaml +++ b/template/workflows/kustomize/draft.yaml @@ -70,3 +70,11 @@ variables: value: "default" description: "the Kubernetes namespace" versions: ">=0.0.1" + - name: "ENABLENAMESPACECREATION" + type: "bool" + kind: "flag" + default: + disablePrompt: true + value: "false" + description: "enable creation of target namespace if it does not exist" + versions: ">=0.0.1" diff --git a/template/workflows/manifests/.github/workflows/azure-kubernetes-service.yml b/template/workflows/manifests/.github/workflows/azure-kubernetes-service.yml index 662199f8..1cfcc7ed 100644 --- a/template/workflows/manifests/.github/workflows/azure-kubernetes-service.yml +++ b/template/workflows/manifests/.github/workflows/azure-kubernetes-service.yml @@ -48,6 +48,7 @@ env: DOCKER_FILE: {{ .Config.GetVariableValue "DOCKERFILE" }} BUILD_CONTEXT_PATH: {{ .Config.GetVariableValue "BUILDCONTEXTPATH" }} NAMESPACE: {{ .Config.GetVariableValue "NAMESPACE" }} + ENABLENAMESPACECREATION: {{ .Config.GetVariableValue "ENABLENAMESPACECREATION" }} {{` jobs: buildImage: @@ -106,6 +107,17 @@ jobs: use-kubelogin: 'true' resource-type: ${{ env.CLUSTER_RESOURCE_TYPE }} + # Create Namespace + - name: Create Namespace + if: ${{ env.ENABLENAMESPACECREATION == 'true' }} + run: | + kubectl get namespace ${{ env.NAMESPACE }} || kubectl create namespace ${{ env.NAMESPACE }} + + # Validate Namespace exists + - name: Validate Namespace Exists + run: | + kubectl get namespace ${{ env.NAMESPACE }} + # Checks if the AKS cluster is private - name: Is private cluster if: ${{ env.CLUSTER_RESOURCE_TYPE != 'Microsoft.ContainerService/fleets' }} @@ -127,4 +139,4 @@ jobs: private-cluster: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' }} namespace: ${{ env.NAMESPACE }} resource-type: ${{ env.CLUSTER_RESOURCE_TYPE }} -`}} \ No newline at end of file +`}} diff --git a/template/workflows/manifests/draft.yaml b/template/workflows/manifests/draft.yaml index 014ab065..b94698e7 100644 --- a/template/workflows/manifests/draft.yaml +++ b/template/workflows/manifests/draft.yaml @@ -70,3 +70,11 @@ variables: value: "default" description: "the Kubernetes namespace" versions: ">=0.0.1" + - name: "ENABLENAMESPACECREATION" + type: "bool" + kind: "flag" + default: + disablePrompt: true + value: "false" + description: "enable creation of target namespace if it does not exist" + versions: ">=0.0.1"