diff --git a/Dockerfile b/Dockerfile index 7b2d1b67..ca798ef2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,6 @@ ENV PATH "$PATH:/draft/az-cli-env/bin" RUN apk add github-cli COPY . ./ -RUN make go-generate RUN go mod download ENTRYPOINT ["go"] \ No newline at end of file diff --git a/Makefile b/Makefile index c8659676..06deb0e1 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,7 @@ .PHONY: all -all: go-generate build generate-integrations +all: build generate-integrations -.PHONY: go-generate -go-generate: - rm -r ./pkg/deployments/deployTypes; \ - rm -r ./pkg/workflows/workflows; \ - rm -r ./pkg/addons/addons; \ - GO111MODULE=on go generate ./pkg/workflows/...; \ - .PHONY: test test: run-unit-tests run-e2e-tests-local @@ -18,7 +11,7 @@ run-unit-tests: #TODO: add more e2e tests to the local testing .PHONY: run-e2e-tests-local -run-e2e-tests-local: go-generate build +run-e2e-tests-local: build test/check_info_schema.sh; .PHONY: generate-integrations @@ -32,7 +25,7 @@ build: GO111MODULE=on go build -v -o . .PHONY: build-all -build-all: go-generate build-windows-amd64 build-linux-amd64 build-linux-arm64 build-darwin-amd64 build-darwin-arm64 +build-all: build-windows-amd64 build-linux-amd64 build-linux-arm64 build-darwin-amd64 build-darwin-arm64 .PHONY: build-windows-amd64 build-windows-amd64: diff --git a/cmd/generate-workflow.go b/cmd/generate-workflow.go index 463a00ea..c47bb0b4 100644 --- a/cmd/generate-workflow.go +++ b/cmd/generate-workflow.go @@ -8,11 +8,11 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/Azure/draft/pkg/handlers" "github.com/Azure/draft/pkg/prompts" "github.com/Azure/draft/pkg/templatewriter" + "github.com/Azure/draft/pkg/cmdhelpers" "github.com/Azure/draft/pkg/templatewriter/writers" - "github.com/Azure/draft/pkg/workflows" - "github.com/Azure/draft/template" ) type generateWorkflowCmd struct { @@ -73,23 +73,25 @@ func (gwc *generateWorkflowCmd) generateWorkflows() error { } } - workflow := workflows.CreateWorkflowsFromEmbedFS(template.Workflows, gwc.dest) - draftConfig, err := workflow.GetConfig(gwc.deployType) + t, err := handlers.GetTemplate(fmt.Sprintf("github-workflow-%s", gwc.deployType), "", gwc.dest, gwc.templateWriter) if err != nil { - return fmt.Errorf("get config: %w", err) + return fmt.Errorf("failed to get template: %e", err) + } + if t == nil { + return fmt.Errorf("template is nil") } - draftConfig.VariableMapToDraftConfig(flagVariablesMap) + t.Config.VariableMapToDraftConfig(flagVariablesMap) - if err = prompts.RunPromptsFromConfigWithSkips(draftConfig); err != nil { + if err = prompts.RunPromptsFromConfigWithSkips(t.Config); err != nil { return err } - if err := workflows.UpdateProductionDeployments(gwc.deployType, gwc.dest, draftConfig, gwc.templateWriter); err != nil { + if err := cmdhelpers.UpdateProductionDeployments(gwc.deployType, gwc.dest, t.Config, gwc.templateWriter); err != nil { return fmt.Errorf("update production deployments: %w", err) } - return workflow.CreateWorkflowFiles(gwc.deployType, draftConfig, gwc.templateWriter) + return t.Generate() } func flagVariablesToMap(flagVariables []string) map[string]string { diff --git a/pkg/workflows/github_workflow.go b/pkg/cmdhelpers/github_workflow.go similarity index 79% rename from pkg/workflows/github_workflow.go rename to pkg/cmdhelpers/github_workflow.go index ec5f94f7..2fde970c 100644 --- a/pkg/workflows/github_workflow.go +++ b/pkg/cmdhelpers/github_workflow.go @@ -1,6 +1,6 @@ -package workflows +package cmdhelpers -//GitHubWorkflow is a rough struct to allow for yaml editing including deletion of Job steps +// GitHubWorkflow is a rough struct to allow for yaml editing including deletion of Job steps type GitHubWorkflow struct { Name string On on `yaml:"on"` diff --git a/pkg/workflows/workflows.go b/pkg/cmdhelpers/workflow_helpers.go similarity index 88% rename from pkg/workflows/workflows.go rename to pkg/cmdhelpers/workflow_helpers.go index 5d81db39..889536c0 100644 --- a/pkg/workflows/workflows.go +++ b/pkg/cmdhelpers/workflow_helpers.go @@ -1,11 +1,9 @@ -package workflows +package cmdhelpers import ( - "embed" "errors" "fmt" "io/fs" - "io/ioutil" "os" "path" @@ -17,7 +15,6 @@ import ( log "github.com/sirupsen/logrus" "github.com/Azure/draft/pkg/config" - "github.com/Azure/draft/pkg/embedutils" "github.com/Azure/draft/pkg/osutil" "github.com/Azure/draft/pkg/templatewriter" ) @@ -61,7 +58,7 @@ func UpdateProductionDeployments(deployType, dest string, draftConfig *config.Dr func setDeploymentContainerImage(filePath, productionImage string) error { decode := scheme.Codecs.UniversalDeserializer().Decode - file, err := ioutil.ReadFile(filePath) + file, err := os.ReadFile(filePath) if err != nil { return err } @@ -97,7 +94,7 @@ func setDeploymentContainerImage(filePath, productionImage string) error { } func setHelmContainerImage(filePath, productionImage string, templateWriter templatewriter.TemplateWriter) error { - file, err := ioutil.ReadFile(filePath) + file, err := os.ReadFile(filePath) if err != nil { return err } @@ -146,23 +143,6 @@ func (w *Workflows) GetConfig(deployType string) (*config.DraftConfig, error) { return val, nil } -func CreateWorkflowsFromEmbedFS(workflowTemplates embed.FS, dest string) *Workflows { - deployMap, err := embedutils.EmbedFStoMap(workflowTemplates, parentDirName) - if err != nil { - log.Fatal(err) - } - - w := &Workflows{ - workflows: deployMap, - Dest: dest, - configs: make(map[string]*config.DraftConfig), - workflowTemplates: workflowTemplates, - } - w.populateConfigs() - - return w -} - func (w *Workflows) populateConfigs() { for deployType := range w.workflows { draftConfig, err := w.loadConfig(deployType) diff --git a/pkg/workflows/service_types.go b/pkg/cmdhelpers/workflow_service_types.go similarity index 92% rename from pkg/workflows/service_types.go rename to pkg/cmdhelpers/workflow_service_types.go index c88ab7eb..6f349721 100644 --- a/pkg/workflows/service_types.go +++ b/pkg/cmdhelpers/workflow_service_types.go @@ -1,8 +1,7 @@ -package workflows +package cmdhelpers import ( "errors" - "io/ioutil" "os" "gopkg.in/yaml.v3" @@ -49,7 +48,7 @@ func (hpy *HelmProductionYaml) GetServiceName() string { } func (hpy *HelmProductionYaml) LoadFromFile(filePath string) error { - file, err := ioutil.ReadFile(filePath) + file, err := os.ReadFile(filePath) if err != nil { return err } @@ -63,7 +62,7 @@ func (hpy *HelmProductionYaml) WriteToFile(filePath string) error { return err } - return ioutil.WriteFile(filePath, currYaml, 0755) + return os.WriteFile(filePath, currYaml, 0755) } type ServiceYaml struct { @@ -84,7 +83,10 @@ func (sy *ServiceYaml) GetServiceName() string { func (sy *ServiceYaml) LoadFromFile(filePath string) error { decode := scheme.Codecs.UniversalDeserializer().Decode - file, err := ioutil.ReadFile(filePath) + file, err := os.ReadFile(filePath) + if err != nil { + return err + } k8sObj, _, err := decode(file, nil, nil) if err != nil { return err diff --git a/pkg/fixtures/validatetemplate.go b/pkg/fixtures/validatetemplate.go index 88ea48f0..3224e607 100644 --- a/pkg/fixtures/validatetemplate.go +++ b/pkg/fixtures/validatetemplate.go @@ -16,7 +16,20 @@ func ValidateContentAgainstFixture(generatedContent []byte, fixturePath string) } if normalizeWhitespace(fixtureContent) != normalizeWhitespace(generatedContent) { - return errors.New("generated content does not match fixture") + genWords := strings.Split(normalizeWhitespace(generatedContent), " ") + fixtureWords := strings.Split(normalizeWhitespace(fixtureContent), " ") + differingWords := []string{} + for i, word := range genWords { + if 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]) + } + } + + return errors.New(fmt.Sprintf("generated content does not match fixture: %s", strings.Join(differingWords, ", "))) } return nil diff --git a/pkg/fixtures/workflows/azurepipelines/manifest/.pipelines/azure-kubernetes-service.yaml b/pkg/fixtures/workflows/azurepipelines/manifests/.pipelines/azure-kubernetes-service.yaml similarity index 100% rename from pkg/fixtures/workflows/azurepipelines/manifest/.pipelines/azure-kubernetes-service.yaml rename to pkg/fixtures/workflows/azurepipelines/manifests/.pipelines/azure-kubernetes-service.yaml 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 new file mode 100644 index 00000000..c11b857b --- /dev/null +++ b/pkg/fixtures/workflows/github/helm/.github/workflows/azure-kubernetes-service-helm.yml @@ -0,0 +1,134 @@ +# This workflow will build and push an application to a Azure Kubernetes Service (AKS) cluster when you push your code +# +# This workflow assumes you have already created the target AKS cluster and have created an Azure Container Registry (ACR) +# The ACR should be attached to the AKS cluster +# For instructions see: +# - https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough-portal +# - https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal +# - https://learn.microsoft.com/en-us/azure/aks/cluster-container-registry-integration?tabs=azure-cli#configure-acr-integration-for-existing-aks-clusters +# - https://github.com/Azure/aks-create-action +# +# To configure this workflow: +# +# 1. Set the following secrets in your repository (instructions for getting these +# https://docs.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux)): +# - AZURE_CLIENT_ID +# - AZURE_TENANT_ID +# - AZURE_SUBSCRIPTION_ID +# +# 2. Set the following environment variables (or replace the values below): +# - ACR_RESOURCE_GROUP (resource group of your ACR) +# - AZURE_CONTAINER_REGISTRY (name of your container registry / ACR) +# - CONTAINER_NAME (name of the container image you would like to push up to your ACR) +# - CLUSTER_RESOURCE_GROUP (where your cluster is deployed) +# - CLUSTER_NAME (name of your AKS cluster) +# - DOCKER_FILE (path to your Dockerfile) +# - BUILD_CONTEXT_PATH (path to the context of your Dockerfile) +# - CHART_PATH (path to your helm chart) +# - CHART_OVERRIDE_PATH (path to your helm chart with override values) +# - CHART_OVERRIDES (override values for your helm chart) +# - NAMESPACE (namespace to deploy your application) +# +# For more information on GitHub Actions for Azure, refer to https://github.com/Azure/Actions +# For more samples to get started with GitHub Action workflows to deploy to Azure, refer to https://github.com/Azure/actions-workflow-samples +# For more options with the actions used below please refer to https://github.com/Azure/login + +name: testWorkflow + +on: + push: + branches: [testBranch] + workflow_dispatch: + +env: + ACR_RESOURCE_GROUP: testAcrRG + AZURE_CONTAINER_REGISTRY: testAcr + CONTAINER_NAME: testContainer + CLUSTER_RESOURCE_GROUP: testClusterRG + CLUSTER_NAME: testCluster + DOCKER_FILE: ./Dockerfile + BUILD_CONTEXT_PATH: test + CHART_PATH: testPath + CHART_OVERRIDE_PATH: testOverridePath + CHART_OVERRIDES: replicas:2 + NAMESPACE: default + +jobs: + buildImage: + permissions: + contents: read + id-token: write + runs-on: ubuntu-latest + steps: + # Checks out the repository this file is in + - uses: actions/checkout@v3 + + # Logs in with your Azure credentials + - name: Azure login + uses: azure/login@v1.4.6 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + # Builds and pushes an image up to your Azure Container Registry + - name: Build and push image to ACR + run: | + az acr build --image ${{ env.CONTAINER_NAME }}:${{ github.sha }} --registry ${{ env.AZURE_CONTAINER_REGISTRY }} -g ${{ env.ACR_RESOURCE_GROUP }} -f ${{ env.DOCKER_FILE }} ${{ env.BUILD_CONTEXT_PATH }} + deploy: + permissions: + actions: read + contents: read + id-token: write + runs-on: ubuntu-latest + needs: [buildImage] + steps: + # Checks out the repository this file is in + - uses: actions/checkout@v3 + + # Logs in with your Azure credentials + - name: Azure login + uses: azure/login@v1.4.6 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + # Use kubelogin to configure your kubeconfig for Azure auth + - name: Set up kubelogin for non-interactive login + uses: azure/use-kubelogin@v1 + with: + kubelogin-version: "v0.0.25" + + # Retrieves your Azure Kubernetes Service cluster's kubeconfig file + - name: Get K8s context + uses: azure/aks-set-context@v3 + with: + resource-group: ${{ env.CLUSTER_RESOURCE_GROUP }} + cluster-name: ${{ env.CLUSTER_NAME }} + admin: "false" + use-kubelogin: "true" + + # Checks if the AKS cluster is private + - name: Is private cluster + id: isPrivate + run: | + result=$(az aks show --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --query "apiServerAccessProfile.enablePrivateCluster") + echo "PRIVATE_CLUSTER=$result" >> "$GITHUB_OUTPUT" + + # Deploys application + - name: Deploy application on private cluster + 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) + 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) + + if [ $exitCode -ne 0 ]; then + exit $exitCode + fi + + - name: Deploy application on public cluster + if: steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' + 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 diff --git a/pkg/fixtures/workflows/azure-kubernetes-service-kustomize.yml b/pkg/fixtures/workflows/github/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml similarity index 100% rename from pkg/fixtures/workflows/azure-kubernetes-service-kustomize.yml rename to pkg/fixtures/workflows/github/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml diff --git a/pkg/fixtures/workflows/azure-kubernetes-service.yml b/pkg/fixtures/workflows/github/manifests/.github/workflows/azure-kubernetes-service.yml similarity index 100% rename from pkg/fixtures/workflows/azure-kubernetes-service.yml rename to pkg/fixtures/workflows/github/manifests/.github/workflows/azure-kubernetes-service.yml diff --git a/pkg/handlers/template_test.go b/pkg/handlers/template_test.go index 7083f857..e0c6aeca 100644 --- a/pkg/handlers/template_test.go +++ b/pkg/handlers/template_test.go @@ -360,6 +360,7 @@ func TestTemplateHandlerValidation(t *testing.T) { }, }, { +<<<<<<< HEAD name: "manifest deployment vars with err from validators", templateName: "deployment-manifests", fixturesBaseDir: "../fixtures/deployments/manifest", @@ -423,6 +424,8 @@ func TestTemplateHandlerValidation(t *testing.T) { expectedErr: fmt.Errorf("invalid label: *myTestApp"), }, { +======= +>>>>>>> origin name: "valid helm workflow", templateName: "github-workflow-helm", fixturesBaseDir: "../fixtures/workflows/github/helm", @@ -446,8 +449,12 @@ func TestTemplateHandlerValidation(t *testing.T) { "CHARTOVERRIDES": "replicas:2", "NAMESPACE": "default", }, +<<<<<<< HEAD }, { +======= + }, { +>>>>>>> origin name: "valid helm workflow", templateName: "github-workflow-kustomize", fixturesBaseDir: "../fixtures/workflows/github/kustomize", @@ -467,8 +474,12 @@ func TestTemplateHandlerValidation(t *testing.T) { "BUILDCONTEXTPATH": "test", "NAMESPACE": "default", }, +<<<<<<< HEAD }, { +======= + }, { +>>>>>>> origin name: "valid manifest workflow", templateName: "github-workflow-manifests", fixturesBaseDir: "../fixtures/workflows/github/manifests", @@ -489,6 +500,7 @@ func TestTemplateHandlerValidation(t *testing.T) { "NAMESPACE": "default", }, }, +<<<<<<< HEAD { name: "valid hpa manifest", templateName: "horizontalPodAutoscaler-manifests", @@ -525,6 +537,8 @@ func TestTemplateHandlerValidation(t *testing.T) { "PARTOF": "test-app-project", }, }, +======= +>>>>>>> origin } for _, tt := range tests { diff --git a/pkg/providers/providersutils_test.go b/pkg/providers/providersutils_test.go index 804a4cab..1cca5bc6 100644 --- a/pkg/providers/providersutils_test.go +++ b/pkg/providers/providersutils_test.go @@ -6,14 +6,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestLoggedInToAz(t *testing.T) { - assert.False(t, IsLoggedInToAz(), "AZ is returning logged in even when logged out") -} - -func TestLoggedInToGh(t *testing.T) { - assert.False(t, IsLoggedInToGh(), "Github is returning logged in even when logged out") -} - func TestCheckAzCliInstalled(t *testing.T) { var err error CheckAzCliInstalled() diff --git a/pkg/workflows/charts/production.yaml b/pkg/workflows/charts/production.yaml deleted file mode 100644 index dc887970..00000000 --- a/pkg/workflows/charts/production.yaml +++ /dev/null @@ -1,8 +0,0 @@ -image: - repository: "test" - pullPolicy: Always - tag: "latest" -service: - annotations: {} - type: LoadBalancer - port: 80 diff --git a/pkg/workflows/manifests/deployment.yaml b/pkg/workflows/manifests/deployment.yaml deleted file mode 100644 index d339c904..00000000 --- a/pkg/workflows/manifests/deployment.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: test - labels: - app: test - kubernetes.azure.com/generator: draft -spec: - replicas: 1 - selector: - matchLabels: - app: test - template: - metadata: - labels: - app: test - spec: - containers: - - name: test - image: test - ports: - - containerPort: 8000 \ No newline at end of file diff --git a/pkg/workflows/overlays/production/deployment.yaml b/pkg/workflows/overlays/production/deployment.yaml deleted file mode 100644 index 11621fba..00000000 --- a/pkg/workflows/overlays/production/deployment.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: test - labels: - kubernetes.azure.com/generator: draft -spec: - template: - spec: - containers: - - name: test - image: acr.test:latest \ No newline at end of file diff --git a/pkg/workflows/workflows_test.go b/pkg/workflows/workflows_test.go deleted file mode 100644 index 1008a09f..00000000 --- a/pkg/workflows/workflows_test.go +++ /dev/null @@ -1,666 +0,0 @@ -package workflows - -import ( - "errors" - "fmt" - "github.com/Azure/draft/pkg/config" - "github.com/Azure/draft/pkg/embedutils" - "github.com/Azure/draft/pkg/fixtures" - "github.com/Azure/draft/pkg/templatewriter/writers" - "io" - "io/fs" - "io/ioutil" - "os" - "testing" - "testing/fstest" - - "github.com/Azure/draft/template" - "github.com/stretchr/testify/assert" - - appsv1 "k8s.io/api/apps/v1" - "k8s.io/client-go/kubernetes/scheme" -) - -func TestCreateWorkflows(t *testing.T) { - dest := "." - templateWriter := &writers.LocalFSWriter{} - draftConfig := &config.DraftConfig{ - Variables: []*config.BuilderVar{ - { - Name: "WORKFLOWNAME", - Value: "testWorkflow", - }, - { - Name: "BRANCHNAME", - Value: "testBranch", - }, - { - Name: "ACRRESOURCEGROUP", - Value: "testAcrRG", - }, - { - Name: "AZURECONTAINERREGISTRY", - Value: "testAcr", - }, - { - Name: "CONTAINERNAME", - Value: "testContainer", - }, - { - Name: "CLUSTERRESOURCEGROUP", - Value: "testClusterRG", - }, - { - Name: "CLUSTERNAME", - Value: "testCluster", - }, - { - Name: "KUSTOMIZEPATH", - Value: "./overlays/production", - }, - { - Name: "DEPLOYMENTMANIFESTPATH", - Value: "./manifests", - }, - { - Name: "DOCKERFILE", - Value: "./Dockerfile", - }, - { - Name: "BUILDCONTEXTPATH", - Value: ".", - }, - { - Name: "CHARTPATH", - Value: "testPath", - }, - { - Name: "CHARTOVERRIDEPATH", - Value: "testOverridePath", - }, - { - Name: "CHARTOVERRIDES", - Value: "replicas:2", - }, - { - Name: "NAMESPACE", - Value: "default", - }, - }, - } - draftConfigNoRoot := &config.DraftConfig{ - Variables: []*config.BuilderVar{ - { - Name: "WORKFLOWNAME", - Value: "testWorkflow", - }, - { - Name: "BRANCHNAME", - Value: "testBranch", - }, - { - Name: "ACRRESOURCEGROUP", - Value: "testAcrRG", - }, - { - Name: "AZURECONTAINERREGISTRY", - Value: "testAcr", - }, - { - Name: "CONTAINERNAME", - Value: "testContainer", - }, - { - Name: "CLUSTERRESOURCEGROUP", - Value: "testClusterRG", - }, - { - Name: "CLUSTERNAME", - Value: "testCluster", - }, - { - Name: "KUSTOMIZEPATH", - Value: "./overlays/production", - }, - { - Name: "DEPLOYMENTMANIFESTPATH", - Value: "./manifests", - }, - { - Name: "DOCKERFILE", - Value: "./Dockerfile", - }, - { - Name: "BUILDCONTEXTPATH", - Value: "test", - }, - { - Name: "CHARTPATH", - Value: "testPath", - }, - { - Name: "CHARTOVERRIDEPATH", - Value: "testOverridePath", - }, - { - Name: "CHARTOVERRIDES", - Value: "replicas:2", - }, - { - Name: "NAMESPACE", - Value: "default", - }, - }, - } - - tests := []struct { - name string - deployType string - shouldError bool - tempDirPath string - tempFileName string - tempPath string - expectedFile string - fixturePath string - cleanUp func() - }{ - { - name: "helm", - deployType: "helm", - shouldError: false, - tempDirPath: "charts", - tempFileName: "charts/production.yaml", - tempPath: "../../test/templates/helm/charts/production.yaml", - expectedFile: ".github/workflows/azure-kubernetes-service-helm.yml", - fixturePath: "../fixtures/workflows/azure-kubernetes-service-helm.yml", - cleanUp: func() { - os.Remove(".charts") - os.Remove(".github") - }, - }, - { - name: "kustomize", - deployType: "kustomize", - shouldError: false, - tempDirPath: "overlays/production", - tempFileName: "overlays/production/deployment.yaml", - tempPath: "../../test/templates/kustomize/overlays/production/deployment.yaml", - expectedFile: ".github/workflows/azure-kubernetes-service-kustomize.yml", - fixturePath: "../fixtures/workflows/azure-kubernetes-service-kustomize.yml", - cleanUp: func() { - os.Remove(".overlays") - os.Remove(".github") - }, - }, - { - name: "manifests", - deployType: "manifests", - shouldError: false, - tempDirPath: "manifests", - tempFileName: "manifests/deployment.yaml", - tempPath: "../../test/templates/manifests/manifests/deployment.yaml", - expectedFile: ".github/workflows/azure-kubernetes-service.yml", - fixturePath: "../fixtures/workflows/azure-kubernetes-service.yml", - cleanUp: func() { - os.Remove(".manifests") - os.Remove(".github") - }, - }, - { - name: "missing manifest", - deployType: "manifests", - shouldError: true, - tempDirPath: "manifests", - tempFileName: "manifests/deployment.yaml", - tempPath: "../../test/templates/manifests/manifests/deployment.yaml", - cleanUp: func() { - os.Remove(".manifests") - os.Remove(".github") - }, - }, - { - name: "invalid deploy type", - deployType: "invalid", - shouldError: true, - tempDirPath: "manifests", - tempFileName: "manifests/deployment.yaml", - tempPath: "../../test/templates/manifests/manifests/deployment.yaml", - cleanUp: func() { - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := createTempDeploymentFile(tt.tempDirPath, tt.tempFileName, tt.tempPath) - assert.Nil(t, err) - - workflows := CreateWorkflowsFromEmbedFS(template.Workflows, dest) - err = workflows.CreateWorkflowFiles(tt.deployType, draftConfig, templateWriter) - if err != nil && !tt.shouldError { - t.Errorf("Default Build Context CreateWorkflows() error = %v, wantErr %v", err, tt.shouldError) - } - - err = workflows.CreateWorkflowFiles(tt.deployType, draftConfigNoRoot, templateWriter) - if err != nil && !tt.shouldError { - t.Errorf("Custom Build Context CreateWorkflows() error = %v, wantErr %v", err, tt.shouldError) - } - - if !tt.shouldError && tt.expectedFile != "" && tt.fixturePath != "" { - generatedContent, err := os.ReadFile(tt.expectedFile) - assert.Nil(t, err) - - // Validate against the fixture - err = fixtures.ValidateContentAgainstFixture(generatedContent, tt.fixturePath) - assert.Nil(t, err, "Generated content does not match the fixture for %s", tt.deployType) - } - - tt.cleanUp() - }) - } -} - -func TestUpdateProductionDeploymentsValid(t *testing.T) { - testTemplateWriter := &writers.LocalFSWriter{} - - //test for valid helm deployment file - helmFileName, _ := createTempManifest("../../test/templates/helm_prod_values.yaml") - defer os.Remove(helmFileName) - - assert.Nil(t, setHelmContainerImage(helmFileName, "testImage", testTemplateWriter)) - - helmDeploy := &HelmProductionYaml{} - assert.Nil(t, helmDeploy.LoadFromFile(helmFileName)) - assert.Equal(t, "testImage", helmDeploy.Image.Repository) - - //test for valid deployment file - deploymentFileName, _ := createTempManifest("../../test/templates/deployment.yaml") - defer os.Remove(deploymentFileName) - - assert.Nil(t, setDeploymentContainerImage(deploymentFileName, "testImage")) - decode := scheme.Codecs.UniversalDeserializer().Decode - file, err := ioutil.ReadFile(deploymentFileName) - assert.Nil(t, err) - - k8sObj, _, err := decode(file, nil, nil) - assert.Nil(t, err) - - deploy, ok := k8sObj.(*appsv1.Deployment) - assert.True(t, ok) - assert.Equal(t, "testImage", deploy.Spec.Template.Spec.Containers[0].Image) -} - -func TestUpdateProductionDeploymentsInvalid(t *testing.T) { - testTemplateWriter := &writers.LocalFSWriter{} - - //test for invalid helm deployment file - tempFile, err := ioutil.TempFile("", "*.yaml") - assert.Nil(t, err) - defer os.Remove(tempFile.Name()) - yamlData := []byte(`not a valid yaml`) - _, err = tempFile.Write(yamlData) - assert.Nil(t, err) - err = tempFile.Close() - assert.Nil(t, err) - assert.NotNil(t, setHelmContainerImage(tempFile.Name(), "testImage", testTemplateWriter)) - - //test for invalid deployment file - assert.NotNil(t, setDeploymentContainerImage(tempFile.Name(), "testImage")) - - //test for invalid k8sObj - invalidDeploymentFile, _ := createTempManifest("../../test/templates/invalid_deployment.yaml") - assert.Equal(t, errors.New("could not decode kubernetes deployment"), setDeploymentContainerImage(invalidDeploymentFile, "testImage")) - - //test for unsupported number of containers in the deployment spec - invalidDeploymentFile, _ = createTempManifest("../../test/templates/unsupported_no_of_containers.yaml") - defer os.Remove(invalidDeploymentFile) - assert.Equal(t, errors.New("unsupported number of containers defined in the deployment spec"), setDeploymentContainerImage(invalidDeploymentFile, "testImage")) -} - -func TestUpdateProductionDeploymentsMissing(t *testing.T) { - draftConfig := &config.DraftConfig{ - Variables: []*config.BuilderVar{ - { - Name: "AZURECONTAINERREGISTRY", - Value: "testRegistry", - }, - { - Name: "CONTAINERNAME", - Value: "testContainer", - }, - }, - } - testTemplateWriter := &writers.LocalFSWriter{} - //test for missing deploy type - assert.Nil(t, UpdateProductionDeployments("", ".", draftConfig, testTemplateWriter)) - - //test for missing helm deployment file - assert.NotNil(t, setHelmContainerImage("", "testImage", testTemplateWriter)) - - //test for missing deployment file - assert.NotNil(t, setDeploymentContainerImage("", "testImage")) -} - -func TestLoadConfig(t *testing.T) { - fakeFS, err := createMockWorkflowTemplatesFS() - assert.Nil(t, err) - w, err := createMockWorkflow("workflows", fakeFS) - assert.Nil(t, err) - - cases := []loadConfTestCase{ - {"helm", true}, - {"kustomize", true}, - {"manifests", true}, - {"fake", false}, - {"emptyDir", false}, - {"corrupted", false}, - } - - for _, c := range cases { - if c.isNil { - _, err = w.loadConfig(c.deployType) - assert.Nil(t, err) - } else { - _, err = w.loadConfig(c.deployType) - assert.NotNil(t, err) - } - } -} - -func TestPopulateConfigs(t *testing.T) { - fakeFS, err := createMockWorkflowTemplatesFS() - assert.Nil(t, err) - - w, err := createMockWorkflow("workflows", fakeFS) - assert.Nil(t, err) - - w.populateConfigs() - assert.Equal(t, 5, len(w.configs)) // includes emptyDir and corrupted so 2 additional configs - - w, err = createTestWorkflowEmbed("workflows") - assert.Nil(t, err) - - w.populateConfigs() - assert.Equal(t, 3, len(w.configs)) -} - -func TestCreateWorkflowFiles(t *testing.T) { - templateWriter := &writers.LocalFSWriter{} - draftConfig := &config.DraftConfig{ - Variables: []*config.BuilderVar{ - { - Name: "WORKFLOWNAME", - Value: "testWorkflow", - }, - { - Name: "BRANCHNAME", - Value: "testBranch", - }, - { - Name: "ACRRESOURCEGROUP", - Value: "testAcrRG", - }, - { - Name: "AZURECONTAINERREGISTRY", - Value: "testAcr", - }, - { - Name: "CONTAINERNAME", - Value: "testContainer", - }, - { - Name: "CLUSTERRESOURCEGROUP", - Value: "testClusterRG", - }, - { - Name: "CLUSTERNAME", - Value: "testCluster", - }, - { - Name: "DOCKERFILE", - Value: "./Dockerfile", - }, - { - Name: "BUILDCONTEXTPATH", - Value: ".", - }, - { - Name: "CHARTPATH", - Value: "testPath", - }, - { - Name: "CHARTOVERRIDEPATH", - Value: "testOverridePath", - }, - { - Name: "CHARTOVERRIDES", - Value: "replicas:2", - }, - { - Name: "NAMESPACE", - Value: "default", - }, - { - Name: "PRIVATECLUSTER", - Value: "false", - }, - }, - } - draftConfigNoRoot := &config.DraftConfig{ - Variables: []*config.BuilderVar{ - { - Name: "WORKFLOWNAME", - Value: "testWorkflow", - }, - { - Name: "BRANCHNAME", - Value: "testBranch", - }, - { - Name: "ACRRESOURCEGROUP", - Value: "testAcrRG", - }, - { - Name: "AZURECONTAINERREGISTRY", - Value: "testAcr", - }, - { - Name: "CONTAINERNAME", - Value: "testContainer", - }, - { - Name: "CLUSTERRESOURCEGROUP", - Value: "testClusterRG", - }, - { - Name: "CLUSTERNAME", - Value: "testCluster", - }, - { - Name: "DOCKERFILE", - Value: "./Dockerfile", - }, - { - Name: "BUILDCONTEXTPATH", - Value: "test", - }, - { - Name: "CHARTPATH", - Value: "testPath", - }, - { - Name: "CHARTOVERRIDEPATH", - Value: "testOverridePath", - }, - { - Name: "CHARTOVERRIDES", - Value: "replicas:2", - }, - { - Name: "NAMESPACE", - Value: "default", - }, - { - Name: "PRIVATECLUSTER", - Value: "false", - }, - }, - } - badDraftConfig := &config.DraftConfig{} - - workflowTemplate, err := createMockWorkflowTemplatesFS() - assert.Nil(t, err) - - mockWF, err := createMockWorkflow("workflows", workflowTemplate) - assert.Nil(t, err) - - mockWF.populateConfigs() - - err = mockWF.CreateWorkflowFiles("fakeDeployType", draftConfig, templateWriter) - assert.NotNil(t, err) - - err = mockWF.CreateWorkflowFiles("helm", draftConfig, templateWriter) - assert.Nil(t, err) - os.RemoveAll(".github") - - err = mockWF.CreateWorkflowFiles("helm", draftConfigNoRoot, templateWriter) - assert.Nil(t, err) - os.RemoveAll(".github") - - err = mockWF.CreateWorkflowFiles("helm", badDraftConfig, templateWriter) - assert.NotNil(t, err) - os.RemoveAll(".github") -} - -type loadConfTestCase struct { - deployType string - isNil bool -} - -func createTempManifest(path string) (string, error) { - file, err := ioutil.TempFile("", "*.yaml") - if err != nil { - return "", err - } - defer file.Close() - - var source *os.File - source, err = os.Open(path) - if err != nil { - return "", err - } - defer source.Close() - - _, err = io.Copy(file, source) - if err != nil { - return "", err - } - return file.Name(), nil -} - -func createTempDeploymentFile(dirPath, fileName, path string) error { - err := os.MkdirAll(dirPath, 0755) - if err != nil { - return err - } - file, err := os.Create(fileName) - if err != nil { - return err - } - defer file.Close() - - var source *os.File - source, err = os.Open(path) - if err != nil { - return err - } - defer source.Close() - - _, err = io.Copy(file, source) - if err != nil { - return err - } - return nil -} - -// Creates a copy of the embeded files in memory and returns a passable fs to use for testing -func createMockWorkflowTemplatesFS() (fs.FS, error) { - rootPath := "workflows/" - embedFiles, err := embedutils.EmbedFStoMapWithFiles(template.Workflows, "workflows") - if err != nil { - return nil, fmt.Errorf("failed to readDir: %w in embeded files", err) - } - - mockFS := fstest.MapFS{} - - for path, file := range embedFiles { - if file.IsDir() { - mockFS[path] = &fstest.MapFile{Mode: fs.ModeDir} - } else { - bytes, err := template.Workflows.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) - } - mockFS[path] = &fstest.MapFile{Data: bytes} - } - } - - mockFS[rootPath+"emptyDir"] = &fstest.MapFile{Mode: fs.ModeDir} - mockFS[rootPath+"corrupted"] = &fstest.MapFile{Mode: fs.ModeDir} - mockFS[rootPath+"corrupted/draft.yaml"] = &fstest.MapFile{Data: []byte("fake yaml data")} - - return mockFS, nil -} - -func createMockWorkflow(dirPath string, mockWorkflowTemplates fs.FS) (*Workflows, error) { - dest := "." - - deployMap, err := fsToMap(mockWorkflowTemplates, dirPath) - if err != nil { - return nil, fmt.Errorf("failed fsToMap: %w", err) - } - - w := &Workflows{ - workflows: deployMap, - Dest: dest, - configs: make(map[string]*config.DraftConfig), - workflowTemplates: mockWorkflowTemplates, - } - - return w, nil -} - -func createTestWorkflowEmbed(dirPath string) (*Workflows, error) { - dest := "." - - deployMap, err := embedutils.EmbedFStoMap(template.Workflows, "workflows") - if err != nil { - return nil, fmt.Errorf("failed to create deployMap: %w", err) - } - - w := &Workflows{ - workflows: deployMap, - Dest: dest, - configs: make(map[string]*config.DraftConfig), - workflowTemplates: template.Workflows, - } - - return w, nil -} - -func fsToMap(fsFS fs.FS, path string) (map[string]fs.DirEntry, error) { - files, err := fs.ReadDir(fsFS, path) - if err != nil { - return nil, fmt.Errorf("failed to ReadDir: %w", err) - } - - mapping := make(map[string]fs.DirEntry) - - for _, f := range files { - if f.IsDir() { - mapping[f.Name()] = f - } - } - - return mapping, nil -} diff --git a/template/azurePipelines/manifests/draft.yaml b/template/azurePipelines/manifests/draft.yaml index 755c0e51..1a6b4653 100644 --- a/template/azurePipelines/manifests/draft.yaml +++ b/template/azurePipelines/manifests/draft.yaml @@ -1,4 +1,4 @@ -templateName: "azure-pipeline-manifest" +templateName: "azure-pipeline-manifests" description: "Azure Pipeline for deploying a containerized application to AKS using kubernetes manifests" versions: "0.0.1" defaultVersion: "0.0.1" diff --git a/template/workflows.go b/template/workflows.go deleted file mode 100644 index 083c250a..00000000 --- a/template/workflows.go +++ /dev/null @@ -1,8 +0,0 @@ -package template - -import "embed" - -var ( - //go:embed all:workflows - Workflows embed.FS -) 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 68d207bb..0a39ee85 100644 --- a/template/workflows/helm/.github/workflows/azure-kubernetes-service-helm.yml +++ b/template/workflows/helm/.github/workflows/azure-kubernetes-service-helm.yml @@ -33,25 +33,25 @@ # For more samples to get started with GitHub Action workflows to deploy to Azure, refer to https://github.com/Azure/actions-workflow-samples # For more options with the actions used below please refer to https://github.com/Azure/login -name: {{.WORKFLOWNAME}} +name: {{ .Config.GetVariableValue "WORKFLOWNAME"}} on: push: - branches: [{{.BRANCHNAME}}] + branches: [{{.Config.GetVariableValue "BRANCHNAME"}}] workflow_dispatch: env: - ACR_RESOURCE_GROUP: {{.ACRRESOURCEGROUP}} - AZURE_CONTAINER_REGISTRY: {{.AZURECONTAINERREGISTRY}} - CONTAINER_NAME: {{.CONTAINERNAME}} - CLUSTER_RESOURCE_GROUP: {{.CLUSTERRESOURCEGROUP}} - CLUSTER_NAME: {{.CLUSTERNAME}} - DOCKER_FILE: {{.DOCKERFILE}} - BUILD_CONTEXT_PATH: {{.BUILDCONTEXTPATH}} - CHART_PATH: {{.CHARTPATH}} - CHART_OVERRIDE_PATH: {{.CHARTOVERRIDEPATH}} - CHART_OVERRIDES: {{.CHARTOVERRIDES}} - NAMESPACE: {{.NAMESPACE}} + ACR_RESOURCE_GROUP: {{ .Config.GetVariableValue "ACRRESOURCEGROUP" }} + AZURE_CONTAINER_REGISTRY: {{ .Config.GetVariableValue "AZURECONTAINERREGISTRY" }} + CONTAINER_NAME: {{ .Config.GetVariableValue "CONTAINERNAME" }} + CLUSTER_RESOURCE_GROUP: {{ .Config.GetVariableValue "CLUSTERRESOURCEGROUP" }} + CLUSTER_NAME: {{ .Config.GetVariableValue "CLUSTERNAME" }} + DOCKER_FILE: {{ .Config.GetVariableValue "DOCKERFILE" }} + BUILD_CONTEXT_PATH: {{ .Config.GetVariableValue "BUILDCONTEXTPATH" }} + CHART_PATH: {{ .Config.GetVariableValue "CHARTPATH" }} + CHART_OVERRIDE_PATH: {{ .Config.GetVariableValue "CHARTOVERRIDEPATH" }} + CHART_OVERRIDES: {{ .Config.GetVariableValue "CHARTOVERRIDES" }} + NAMESPACE: {{ .Config.GetVariableValue "NAMESPACE" }} {{` jobs: buildImage: @@ -98,7 +98,7 @@ jobs: - name: Set up kubelogin for non-interactive login uses: azure/use-kubelogin@v1 with: - kubelogin-version: 'v0.0.25' + kubelogin-version: "v0.0.25" # Retrieves your Azure Kubernetes Service cluster's kubeconfig file - name: Get K8s context @@ -106,8 +106,8 @@ jobs: with: resource-group: ${{ env.CLUSTER_RESOURCE_GROUP }} cluster-name: ${{ env.CLUSTER_NAME }} - admin: 'false' - use-kubelogin: 'true' + admin: "false" + use-kubelogin: "true" # Checks if the AKS cluster is private - name: Is private cluster @@ -118,7 +118,7 @@ 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) result=$(az aks command result --resource-group ${{ env.CLUSTER_RESOURCE_GROUP }} --name ${{ env.CLUSTER_NAME }} --command-id $command_id) @@ -130,6 +130,6 @@ jobs: fi - name: Deploy application on public cluster - if : steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' + if: steps.isPrivate.outputs.PRIVATE_CLUSTER != 'true' 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 `}} diff --git a/template/workflows/helm/draft.yaml b/template/workflows/helm/draft.yaml index b04bf995..31bbe504 100644 --- a/template/workflows/helm/draft.yaml +++ b/template/workflows/helm/draft.yaml @@ -1,6 +1,8 @@ templateName: "github-workflow-helm" description: "This template is used to create a GitHub workflow for building and deploying an app to AKS with Helm" type: "workflow" +versions: "0.0.1" +defaultVersion: "0.0.1" variables: - name: "WORKFLOWNAME" type: "string" @@ -8,42 +10,51 @@ variables: default: value: "Build and deploy an app to AKS with Helm" description: "the name of the workflow" + versions: ">=0.0.1" - name: "BRANCHNAME" type: "string" kind: "repositoryBranch" description: "the Github branch to automatically deploy from" + versions: ">=0.0.1" - name: "ACRRESOURCEGROUP" type: "string" kind: "azureResourceGroup" description: "the ACR resource group" + versions: ">=0.0.1" - name: "AZURECONTAINERREGISTRY" type: "string" kind: "azureContainerRegistry" description: "the Azure container registry name" + versions: ">=0.0.1" - name: "CONTAINERNAME" type: "string" kind: "containerImageName" description: "the container image name" + versions: ">=0.0.1" - name: "CLUSTERRESOURCEGROUP" type: "string" kind: "azureResourceGroup" description: "the AKS cluster resource group" + versions: ">=0.0.1" - name: "CLUSTERNAME" type: "string" kind: "azureManagedCluster" description: "the AKS cluster name" + versions: ">=0.0.1" - name: "DOCKERFILE" type: "string" kind: "filePath" default: value: "./Dockerfile" description: "the path to the Dockerfile" + versions: ">=0.0.1" - name: "BUILDCONTEXTPATH" type: "string" kind: "dirPath" default: value: "." description: "the path to the Docker build context" + versions: ">=0.0.1" - name: "CHARTPATH" type: "string" kind: "dirPath" @@ -51,6 +62,7 @@ variables: disablePrompt: true value: "./charts" description: "the path to the Helm chart" + versions: ">=0.0.1" - name: "CHARTOVERRIDEPATH" type: "string" kind: "dirPath" @@ -58,6 +70,7 @@ variables: disablePrompt: true value: "./charts/production.yaml" description: "the path to the Helm chart override file" + versions: ">=0.0.1" - name: "CHARTOVERRIDES" type: "string" kind: "helmChartOverrides" @@ -65,9 +78,11 @@ variables: disablePrompt: true value: "replicas=2" description: "the Helm chart overrides" + versions: ">=0.0.1" - name: "NAMESPACE" type: "string" kind: "kubernetesNamespace" default: value: "default" description: "the Kubernetes namespace" + 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 1591825f..1988e233 100644 --- a/template/workflows/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml +++ b/template/workflows/kustomize/.github/workflows/azure-kubernetes-service-kustomize.yml @@ -34,23 +34,23 @@ # For more samples to get started with GitHub Action workflows to deploy to Azure, refer to https://github.com/Azure/actions-workflow-samples # For more options with the actions used below please refer to https://github.com/Azure/login -name: {{.WORKFLOWNAME}} +name: {{ .Config.GetVariableValue "WORKFLOWNAME" }} on: push: - branches: [{{.BRANCHNAME}}] + branches: [{{ .Config.GetVariableValue "BRANCHNAME" }}] workflow_dispatch: env: - ACR_RESOURCE_GROUP: {{.ACRRESOURCEGROUP}} - AZURE_CONTAINER_REGISTRY: {{.AZURECONTAINERREGISTRY}} - CONTAINER_NAME: {{.CONTAINERNAME}} - CLUSTER_RESOURCE_GROUP: {{.CLUSTERRESOURCEGROUP}} - CLUSTER_NAME: {{.CLUSTERNAME}} - KUSTOMIZE_PATH: {{.KUSTOMIZEPATH}} - DOCKER_FILE: {{.DOCKERFILE}} - BUILD_CONTEXT_PATH: {{.BUILDCONTEXTPATH}} - NAMESPACE: {{.NAMESPACE}} + ACR_RESOURCE_GROUP: {{ .Config.GetVariableValue "ACRRESOURCEGROUP" }} + AZURE_CONTAINER_REGISTRY: {{ .Config.GetVariableValue "AZURECONTAINERREGISTRY" }} + CONTAINER_NAME: {{ .Config.GetVariableValue "CONTAINERNAME" }} + CLUSTER_RESOURCE_GROUP: {{ .Config.GetVariableValue "CLUSTERRESOURCEGROUP" }} + CLUSTER_NAME: {{ .Config.GetVariableValue "CLUSTERNAME" }} + KUSTOMIZE_PATH: {{ .Config.GetVariableValue "KUSTOMIZEPATH" }} + DOCKER_FILE: {{ .Config.GetVariableValue "DOCKERFILE" }} + BUILD_CONTEXT_PATH: {{ .Config.GetVariableValue "BUILDCONTEXTPATH" }} + NAMESPACE: {{ .Config.GetVariableValue "NAMESPACE" }} {{` jobs: buildImage: diff --git a/template/workflows/kustomize/draft.yaml b/template/workflows/kustomize/draft.yaml index 34bfc63b..ac73ea1a 100644 --- a/template/workflows/kustomize/draft.yaml +++ b/template/workflows/kustomize/draft.yaml @@ -1,6 +1,8 @@ templateName: "github-workflow-kustomize" description: "This template is used to create a GitHub workflow for building and deploying an app to AKS with Kustomize" type: "workflow" +versions: "0.0.1" +defaultVersion: "0.0.1" variables: - name: "WORKFLOWNAME" type: "string" @@ -8,30 +10,37 @@ variables: default: value: "Build and deploy an app to AKS with Kustomize" description: "the name of the workflow" + versions: ">=0.0.1" - name: "BRANCHNAME" type: "string" kind: "repositoryBranch" description: "the Github branch to automatically deploy from" + versions: ">=0.0.1" - name: "ACRRESOURCEGROUP" type: "string" kind: "azureResourceGroup" description: "the ACR resource group" + versions: ">=0.0.1" - name: "AZURECONTAINERREGISTRY" type: "string" kind: "azureContainerRegistry" description: "the Azure container registry name" + versions: ">=0.0.1" - name: "CONTAINERNAME" type: "string" kind: "containerImageName" description: "the container image name" + versions: ">=0.0.1" - name: "CLUSTERRESOURCEGROUP" type: "string" kind: "azureResourceGroup" description: "the AKS cluster resource group" + versions: ">=0.0.1" - name: "CLUSTERNAME" type: "string" kind: "azureManagedCluster" description: "the AKS cluster name" + versions: ">=0.0.1" - name: "KUSTOMIZEPATH" type: "string" kind: "dirPath" @@ -39,21 +48,25 @@ variables: disablePrompt: true value: "./overlays/production" description: "the path to the Kustomize directory" + versions: ">=0.0.1" - name: "DOCKERFILE" type: "string" kind: "filePath" default: value: "./Dockerfile" description: "the path to the Dockerfile" + versions: ">=0.0.1" - name: "BUILDCONTEXTPATH" type: "string" kind: "dirPath" default: value: "." description: "the path to the Docker build context" + versions: ">=0.0.1" - name: "NAMESPACE" type: "string" kind: "kubernetesNamespace" default: value: "default" description: "the Kubernetes namespace" + 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 b0990ed7..7e425e79 100644 --- a/template/workflows/manifests/.github/workflows/azure-kubernetes-service.yml +++ b/template/workflows/manifests/.github/workflows/azure-kubernetes-service.yml @@ -30,23 +30,23 @@ # For more samples to get started with GitHub Action workflows to deploy to Azure, refer to https://github.com/Azure/actions-workflow-samples # For more options with the actions used below please refer to https://github.com/Azure/login -name: {{.WORKFLOWNAME}} +name: {{ .Config.GetVariableValue "WORKFLOWNAME" }} on: push: - branches: [{{.BRANCHNAME}}] + branches: [{{ .Config.GetVariableValue "BRANCHNAME" }}] workflow_dispatch: env: - ACR_RESOURCE_GROUP: {{.ACRRESOURCEGROUP}} - AZURE_CONTAINER_REGISTRY: {{.AZURECONTAINERREGISTRY}} - CONTAINER_NAME: {{.CONTAINERNAME}} - CLUSTER_RESOURCE_GROUP: {{.CLUSTERRESOURCEGROUP}} - CLUSTER_NAME: {{.CLUSTERNAME}} - DEPLOYMENT_MANIFEST_PATH: {{.DEPLOYMENTMANIFESTPATH}} - DOCKER_FILE: {{.DOCKERFILE}} - BUILD_CONTEXT_PATH: {{.BUILDCONTEXTPATH}} - NAMESPACE: {{.NAMESPACE}} + ACR_RESOURCE_GROUP: {{ .Config.GetVariableValue "ACRRESOURCEGROUP" }} + AZURE_CONTAINER_REGISTRY: {{ .Config.GetVariableValue "AZURECONTAINERREGISTRY" }} + CONTAINER_NAME: {{ .Config.GetVariableValue "CONTAINERNAME" }} + CLUSTER_RESOURCE_GROUP: {{ .Config.GetVariableValue "CLUSTERRESOURCEGROUP" }} + CLUSTER_NAME: {{ .Config.GetVariableValue "CLUSTERNAME" }} + DEPLOYMENT_MANIFEST_PATH: {{ .Config.GetVariableValue "DEPLOYMENTMANIFESTPATH" }} + DOCKER_FILE: {{ .Config.GetVariableValue "DOCKERFILE" }} + BUILD_CONTEXT_PATH: {{ .Config.GetVariableValue "BUILDCONTEXTPATH" }} + NAMESPACE: {{ .Config.GetVariableValue "NAMESPACE" }} {{` jobs: buildImage: diff --git a/template/workflows/manifests/draft.yaml b/template/workflows/manifests/draft.yaml index ebfd9d18..c7dac3ef 100644 --- a/template/workflows/manifests/draft.yaml +++ b/template/workflows/manifests/draft.yaml @@ -1,6 +1,8 @@ -templateName: "github-workflow-manifest" +templateName: "github-workflow-manifests" description: "This template is used to create a GitHub workflow for building and deploying an app to AKS with kubernetes manifests" type: "workflow" +versions: "0.0.1" +defaultVersion: "0.0.1" variables: - name: "WORKFLOWNAME" type: "string" @@ -8,30 +10,37 @@ variables: default: value: "Build and deploy an app to AKS" description: "the name of the workflow" + versions: ">=0.0.1" - name: "BRANCHNAME" type: "string" kind: "repositoryBranch" description: "the Github branch to automatically deploy from" + versions: ">=0.0.1" - name: "ACRRESOURCEGROUP" type: "string" kind: "azureResourceGroup" description: "the ACR resource group" + versions: ">=0.0.1" - name: "AZURECONTAINERREGISTRY" type: "string" kind: "azureContainerRegistry" description: "the Azure container registry name" + versions: ">=0.0.1" - name: "CONTAINERNAME" type: "string" kind: "containerImageName" description: "the container image name" + versions: ">=0.0.1" - name: "CLUSTERRESOURCEGROUP" type: "string" kind: "azureResourceGroup" description: "the AKS cluster resource group" + versions: ">=0.0.1" - name: "CLUSTERNAME" type: "string" kind: "azureManagedCluster" description: "the AKS cluster name" + versions: ">=0.0.1" - name: "DEPLOYMENTMANIFESTPATH" type: "string" kind: "dirPath" @@ -39,21 +48,25 @@ variables: disablePrompt: true value: "./manifests" description: "the path to the Kubernetes deployment manifest" + versions: ">=0.0.1" - name: "DOCKERFILE" type: "string" kind: "filePath" default: value: "./Dockerfile" description: "the path to the Dockerfile" + versions: ">=0.0.1" - name: "BUILDCONTEXTPATH" type: "string" kind: "dirPath" default: value: "." description: "the path to the Docker build context" + versions: ">=0.0.1" - name: "NAMESPACE" type: "string" kind: "kubernetesNamespace" default: value: "default" description: "the Kubernetes namespace" + versions: ">=0.0.1"