diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bab000c0..f776db57 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,19 +5,27 @@ updates: schedule: interval: "weekly" groups: - # Group updates together, so that they are all applied in a single PR. - # Grouped updates are currently in beta and is subject to change. - # xref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups - k8s-go-deps: - patterns: - - "k8s.io/*" - - "sigs.k8s.io/*" - go-deps: - patterns: - - "*" - exclude-patterns: - - "k8s.io/*" - - "sigs.k8s.io/*" + # Group updates together, so that they are all applied in a single PR. + # Grouped updates are currently in beta and is subject to change. + # xref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups + k8s-go-deps: + patterns: + - "k8s.io/*" + - "sigs.k8s.io/*" + go-deps: + patterns: + - "*" + exclude-patterns: + - "k8s.io/*" + - "sigs.k8s.io/*" + - package-ecosystem: "github-actions" + directory: ".github/workflows" + schedule: + interval: weekly + groups: + actions: + patterns: + - "*" - package-ecosystem: "github-actions" directory: "/template/workflows/helm/.github/workflows" schedule: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 99e9493d..82411abc 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,12 +13,12 @@ name: "CodeQL" on: push: - branches: [ main ] + branches: [main] pull_request: # The branches below must be a subset of the branches above - branches: [ main ] + branches: [main] schedule: - - cron: '33 14 * * 4' + - cron: "33 14 * * 4" jobs: analyze: @@ -32,39 +32,39 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'go' ] + language: ["go"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/pkg/addons/addons.go b/pkg/addons/addons.go index 4292552d..97d5de23 100644 --- a/pkg/addons/addons.go +++ b/pkg/addons/addons.go @@ -37,10 +37,13 @@ func GenerateAddon(addons embed.FS, provider, addon, dest string, addonConfig Ad if addonConfig.DraftConfig == nil { return errors.New("DraftConfig is nil") } else { - addonConfig.DraftConfig.ApplyDefaultVariables() + err := addonConfig.DraftConfig.ApplyDefaultVariables() + if err != nil { + return err + } } - if err = osutil.CopyDir(addons, selectedAddonPath, addonDestPath, addonConfig.DraftConfig, templateWriter); err != nil { + if err = osutil.CopyDirWithTemplates(addons, selectedAddonPath, addonDestPath, addonConfig.DraftConfig, templateWriter); err != nil { return err } diff --git a/pkg/addons/addons_test.go b/pkg/addons/addons_test.go index 27bd5592..7f446c38 100644 --- a/pkg/addons/addons_test.go +++ b/pkg/addons/addons_test.go @@ -1,6 +1,8 @@ package addons import ( + "fmt" + "github.com/Azure/draft/pkg/fixtures" "io/ioutil" "os" "testing" @@ -46,7 +48,8 @@ func TestGenerateHelmAddonSuccess(t *testing.T) { Value: "host", }, { - Name: "GENERATORLABEL", + Name: "GENERATORLABEL", + Value: "draft", }, { Name: "service-namespace", @@ -69,6 +72,19 @@ func TestGenerateHelmAddonSuccess(t *testing.T) { err = GenerateAddon(template.Addons, "azure", "webapp_routing", dir, addonConfig, templateWriter) assert.Nil(t, err) + // Validate generated content against the fixture + generatedFilePath := fmt.Sprintf("%s/charts/templates/ingress.yaml", dir) + generatedContent, err := os.ReadFile(generatedFilePath) + assert.Nil(t, err) + + fixturePath := "../fixtures/addons/helm/ingress.yaml" + if _, err := os.Stat(fixturePath); os.IsNotExist(err) { + t.Fatalf("Fixture file does not exist at path: %s", fixturePath) + } + + err = fixtures.ValidateContentAgainstFixture(generatedContent, fixturePath) + assert.Nil(t, err) + assert.Nil(t, remove()) } @@ -90,7 +106,8 @@ func TestGenerateKustomizeAddonSuccess(t *testing.T) { Value: "host", }, { - Name: "GENERATORLABEL", + Name: "GENERATORLABEL", + Value: "draft", }, { Name: "service-namespace", @@ -113,6 +130,19 @@ func TestGenerateKustomizeAddonSuccess(t *testing.T) { err = GenerateAddon(template.Addons, "azure", "webapp_routing", dir, addonConfig, templateWriter) assert.Nil(t, err) + // Validate generated content against the fixture + generatedFilePath := fmt.Sprintf("%s/overlays/production/ingress.yaml", dir) + generatedContent, err := os.ReadFile(generatedFilePath) + assert.Nil(t, err) + + fixturePath := "../fixtures/addons/kustomize/ingress.yaml" + if _, err := os.Stat(fixturePath); os.IsNotExist(err) { + t.Fatalf("Fixture file does not exist at path: %s", fixturePath) + } + + err = fixtures.ValidateContentAgainstFixture(generatedContent, fixturePath) + assert.Nil(t, err) + assert.Nil(t, remove()) } diff --git a/pkg/azurePipelines/azurePipelines.go b/pkg/azurePipelines/azurePipelines.go index f4defc19..c46fee1d 100644 --- a/pkg/azurePipelines/azurePipelines.go +++ b/pkg/azurePipelines/azurePipelines.go @@ -125,7 +125,7 @@ func (p *AzurePipelines) CreatePipelineFiles(deployType string, draftConfig *con return fmt.Errorf("error applying default variables: %w", err) } - if err := osutil.CopyDir(p.pipelineTemplates, srcDir, p.dest, draftConfig, templateWriter); err != nil { + if err := osutil.CopyDirWithTemplates(p.pipelineTemplates, srcDir, p.dest, draftConfig, templateWriter); err != nil { return fmt.Errorf("error copying pipeline files: %w", err) } diff --git a/pkg/azurePipelines/azurePipelines_test.go b/pkg/azurePipelines/azurePipelines_test.go index 7e781083..798d7f4b 100644 --- a/pkg/azurePipelines/azurePipelines_test.go +++ b/pkg/azurePipelines/azurePipelines_test.go @@ -2,6 +2,7 @@ package azurePipelines import ( "fmt" + "github.com/Azure/draft/pkg/fixtures" "os" "testing" @@ -32,7 +33,7 @@ func TestCreatePipelines(t *testing.T) { deployType: "kustomize", shouldError: false, setConfig: func(dc *config.DraftConfig) { - dc.SetVariable("KUSTOMIZEPATH", "test/kustomize/overlays/production") + dc.SetVariable("KUSTOMIZEPATH", "kustomize/overlays/production") }, }, { @@ -40,7 +41,7 @@ func TestCreatePipelines(t *testing.T) { deployType: "manifests", shouldError: false, setConfig: func(dc *config.DraftConfig) { - dc.SetVariable("PIPELINENAME", "some-other-name") + dc.SetVariable("PIPELINENAME", "testPipeline") }, }, { @@ -95,6 +96,19 @@ func TestCreatePipelines(t *testing.T) { assert.Nil(t, err) _, err = os.Stat(pipelineFilePath) assert.Nil(t, err) + + // Read the generated content + generatedContent, err := os.ReadFile(pipelineFilePath) + assert.Nil(t, err) + + // Validate against the fixture file + fixturePath := fmt.Sprintf("../fixtures/pipelines/%s.yaml", tt.deployType) + if _, err := os.Stat(fixturePath); os.IsNotExist(err) { + t.Fatalf("Fixture file does not exist at path: %s", fixturePath) + } + + err = fixtures.ValidateContentAgainstFixture(generatedContent, fixturePath) + assert.Nil(t, err) } err = os.RemoveAll(tempDir) @@ -148,7 +162,7 @@ func newDraftConfig() *config.DraftConfig { { Name: "MANIFESTPATH", Default: config.BuilderVarDefault{ - Value: "manifests", + Value: "test/manifests", }, }, { diff --git a/pkg/config/draftconfig.go b/pkg/config/draftconfig.go index 62dcdc94..fc7c57e3 100644 --- a/pkg/config/draftconfig.go +++ b/pkg/config/draftconfig.go @@ -3,12 +3,21 @@ package config import ( "errors" "fmt" + "io/fs" log "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" ) +const draftConfigFile = "draft.yaml" + type DraftConfig struct { + TemplateName string `yaml:"templateName"` DisplayName string `yaml:"displayName"` + Description string `yaml:"description"` + Type string `yaml:"type"` + Versions string `yaml:"versions"` + DefaultVersion string `yaml:"defaultVersion"` Variables []*BuilderVar `yaml:"variables"` FileNameOverrideMap map[string]string `yaml:"filenameOverrideMap"` } @@ -19,7 +28,9 @@ type BuilderVar struct { Description string `yaml:"description"` ExampleValues []string `yaml:"exampleValues"` Type string `yaml:"type"` + Kind string `yaml:"kind"` Value string `yaml:"value"` + Versions string `yaml:"versions"` } type BuilderVarDefault struct { @@ -28,6 +39,20 @@ type BuilderVarDefault struct { Value string `yaml:"value"` } +func NewConfigFromFS(fileSys fs.FS, path string) (*DraftConfig, error) { + configBytes, err := fs.ReadFile(fileSys, path) + if err != nil { + return nil, err + } + + var draftConfig DraftConfig + if err = yaml.Unmarshal(configBytes, &draftConfig); err != nil { + return nil, err + } + + return &draftConfig, nil +} + func (d *DraftConfig) GetVariableExampleValues() map[string][]string { variableExampleValues := make(map[string][]string) for _, variable := range d.Variables { diff --git a/pkg/config/draftconfig_template_test.go b/pkg/config/draftconfig_template_test.go new file mode 100644 index 00000000..7b937100 --- /dev/null +++ b/pkg/config/draftconfig_template_test.go @@ -0,0 +1,114 @@ +package config + +import ( + "fmt" + "io/fs" + "strings" + "testing" + + "github.com/Azure/draft/template" + "github.com/stretchr/testify/assert" +) + +var allTemplates = map[string]*DraftConfig{} + +var validTemplateTypes = map[string]bool{ + "manifest": true, + "dockerfile": true, + "workflow": true, + "deployment": true, +} + +var validVariableTypes = map[string]bool{ + "string": true, + "bool": true, + "int": true, + "float": true, + "object": true, +} +var validVariableKinds = map[string]bool{ + "azureContainerRegistry": true, + "azureKeyvaultUri": true, + "azureManagedCluster": true, + "azureResourceGroup": true, + "azureServiceConnection": true, + "containerImageName": true, + "containerImageVersion": true, + "dirPath": true, + "filePath": true, + "flag": true, + "helmChartOverrides": true, + "ingressHostName": true, + "kubernetesNamespace": true, + "kubernetesResourceName": true, + "label": true, + "port": true, + "repositoryBranch": true, + "workflowName": true, +} + +/* +This test will validate all the templates in the templates directory have: +1. a unique template name +2. a valid template type +3. a non-empty variable name +4. a valid variable type +5. a valid variable kind + +Append this for more validation +*/ +func TestTempalteValidation(t *testing.T) { + assert.Nil(t, loadTemplatesWithValidation()) +} + +func loadTemplatesWithValidation() error { + return fs.WalkDir(template.Templates, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + if !strings.EqualFold(d.Name(), draftConfigFile) { + return nil + } + + currTemplate, err := NewConfigFromFS(template.Templates, path) + if err != nil { + return err + } + + if currTemplate == nil { + return fmt.Errorf("template %s is nil", path) + } + + if currTemplate.TemplateName == "" { + return fmt.Errorf("template %s has no template name", path) + } + + if _, ok := allTemplates[currTemplate.TemplateName]; ok { + return fmt.Errorf("template %s has a duplicate template name", path) + } + + if _, ok := validTemplateTypes[currTemplate.Type]; !ok { + return fmt.Errorf("template %s has an invalid type: %s", path, currTemplate.Type) + } + + for _, variable := range currTemplate.Variables { + if variable.Name == "" { + return fmt.Errorf("template %s has a variable with no name", path) + } + + if _, ok := validVariableTypes[variable.Type]; !ok { + return fmt.Errorf("template %s has an invalid variable(%s) type: %s", path, variable.Name, variable.Type) + } + + if _, ok := validVariableKinds[variable.Kind]; !ok { + return fmt.Errorf("template %s has an invalid variable kind: %s", path, variable.Kind) + } + } + return nil + }) +} diff --git a/pkg/deployments/deployments.go b/pkg/deployments/deployments.go index f5acba11..5275478c 100644 --- a/pkg/deployments/deployments.go +++ b/pkg/deployments/deployments.go @@ -17,7 +17,7 @@ import ( "github.com/Azure/draft/pkg/templatewriter" ) -var ( +const ( parentDirName = "deployments" configFileName = "draft.yaml" ) @@ -47,7 +47,7 @@ func (d *Deployments) CopyDeploymentFiles(deployType string, deployConfig *confi return fmt.Errorf("create deployment files for deployment type: %w", err) } - if err := osutil.CopyDir(d.deploymentTemplates, srcDir, d.dest, deployConfig, templateWriter); err != nil { + if err := osutil.CopyDirWithTemplates(d.deploymentTemplates, srcDir, d.dest, deployConfig, templateWriter); err != nil { return err } @@ -94,7 +94,7 @@ func (d *Deployments) PopulateConfigs() { } func CreateDeploymentsFromEmbedFS(deploymentTemplates embed.FS, dest string) *Deployments { - deployMap, err := embedutils.EmbedFStoMap(deploymentTemplates, "deployments") + deployMap, err := embedutils.EmbedFStoMap(deploymentTemplates, parentDirName) if err != nil { log.Fatal(err) } diff --git a/pkg/deployments/deployments_test.go b/pkg/deployments/deployments_test.go new file mode 100644 index 00000000..3da9259f --- /dev/null +++ b/pkg/deployments/deployments_test.go @@ -0,0 +1,252 @@ +package deployments + +import ( + "embed" + "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" + "os" + "testing" + "testing/fstest" + + "github.com/Azure/draft/template" + "github.com/stretchr/testify/assert" +) + +var testFS embed.FS + +func TestCreateDeployments(t *testing.T) { + dest := "." + templateWriter := &writers.LocalFSWriter{} + draftConfig := &config.DraftConfig{ + Variables: []*config.BuilderVar{ + {Name: "APPNAME", Value: "testapp"}, + {Name: "NAMESPACE", Value: "default"}, + {Name: "PORT", Value: "80"}, + {Name: "IMAGENAME", Value: "testimage"}, + {Name: "IMAGETAG", Value: "latest"}, + {Name: "GENERATORLABEL", Value: "draft"}, + {Name: "SERVICEPORT", Value: "80"}, + }, + } + + tests := []struct { + name string + deployType string + shouldError bool + tempDirPath string + tempFileName string + tempPath string + fixturePath string + cleanUp func() + }{ + { + name: "helm", + deployType: "helm", + shouldError: false, + tempDirPath: "charts/templates", + tempFileName: "charts/templates/deployment.yaml", + tempPath: "../../test/templates/helm/charts/templates/deployment.yaml", + fixturePath: "../fixtures/deployments/charts/templates/deployment.yaml", + cleanUp: func() { + os.Remove(".charts") + }, + }, + { + name: "unsupported", + deployType: "unsupported", + shouldError: true, + tempDirPath: "test/templates/unsupported", + tempFileName: "test/templates/unsupported/deployment.yaml", + tempPath: "test/templates/unsupported/deployment.yaml", + cleanUp: func() { + os.Remove("deployments") + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fmt.Println("Creating temp file:", tt.tempFileName) + err := createTempDeploymentFile(tt.tempDirPath, tt.tempFileName, tt.tempPath) + assert.Nil(t, err) + + deployments := CreateDeploymentsFromEmbedFS(template.Deployments, dest) + err = deployments.CopyDeploymentFiles(tt.deployType, draftConfig, templateWriter) + if tt.shouldError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + + generatedContent, err := os.ReadFile(tt.tempFileName) + assert.Nil(t, err) + + if _, err := os.Stat(tt.fixturePath); os.IsNotExist(err) { + t.Errorf("Fixture file does not exist at path: %s", tt.fixturePath) + } + + err = fixtures.ValidateContentAgainstFixture(generatedContent, tt.fixturePath) + assert.Nil(t, err) + } + + tt.cleanUp() + }) + } +} + +func TestLoadConfig(t *testing.T) { + fakeFS, err := createMockDeploymentTemplatesFS() + assert.Nil(t, err) + + d, err := createMockDeployments("deployments", fakeFS) + assert.Nil(t, err) + + cases := []loadConfTestCase{ + {"helm", true}, + {"unsupported", false}, + } + + for _, c := range cases { + if c.isNil { + _, err = d.loadConfig(c.deployType) + assert.Nil(t, err) + } else { + _, err = d.loadConfig(c.deployType) + assert.NotNil(t, err) + } + } +} + +func TestPopulateConfigs(t *testing.T) { + fakeFS, err := createMockDeploymentTemplatesFS() + assert.Nil(t, err) + + d, err := createMockDeployments("deployments", fakeFS) + assert.Nil(t, err) + + d.PopulateConfigs() + assert.Equal(t, 3, len(d.configs)) + + d, err = createTestDeploymentEmbed("deployments") + assert.Nil(t, err) + + d.PopulateConfigs() + assert.Equal(t, 3, len(d.configs)) +} + +type loadConfTestCase struct { + deployType string + isNil bool +} + +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 + } + fmt.Printf("file %v\n", file) + defer file.Close() + + var source *os.File + source, err = os.Open(path) + if err != nil { + return err + } + fmt.Printf("source %v\n", source) + defer source.Close() + + _, err = io.Copy(file, source) + if err != nil { + return err + } + return nil +} + +func createMockDeploymentTemplatesFS() (fs.FS, error) { + rootPath := "deplyments/" + embedFiles, err := embedutils.EmbedFStoMapWithFiles(template.Deployments, "deployments") + 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.Deployments.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failes 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 createMockDeployments(dirPath string, mockDeployments fs.FS) (*Deployments, error) { + dest := "." + + deployMap, err := fsToMap(mockDeployments, dirPath) + if err != nil { + return nil, fmt.Errorf("failed fsToMap: %w", err) + } + + d := &Deployments{ + deploys: deployMap, + dest: dest, + configs: make(map[string]*config.DraftConfig), + deploymentTemplates: mockDeployments, + } + + return d, nil +} + +func createTestDeploymentEmbed(dirPath string) (*Deployments, error) { + dest := "." + + deployMap, err := embedutils.EmbedFStoMap(template.Deployments, "deployments") + if err != nil { + return nil, fmt.Errorf("failed to create deployMap: %w", err) + } + + d := &Deployments{ + deploys: deployMap, + dest: dest, + configs: make(map[string]*config.DraftConfig), + deploymentTemplates: template.Deployments, + } + + return d, 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/pkg/fixtures/addons/helm/ingress.yaml b/pkg/fixtures/addons/helm/ingress.yaml new file mode 100644 index 00000000..b4d05333 --- /dev/null +++ b/pkg/fixtures/addons/helm/ingress.yaml @@ -0,0 +1,33 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.azure.com/tls-cert-keyvault-uri: "test.uri" + kubernetes.azure.com/use-osm-mtls: "false" + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + nginx.ingress.kubernetes.io/configuration-snippet: |2- + + proxy_ssl_name "default.test-namespace.cluster.local"; + nginx.ingress.kubernetes.io/proxy-ssl-secret: kube-system/osm-ingress-client-cert + nginx.ingress.kubernetes.io/proxy-ssl-verify: "on" + name: "test-service" + namespace: "test-namespace" + labels: + kubernetes.azure.com/generator: draft +spec: + ingressClassName: webapprouting.kubernetes.azure.com + rules: + - host: "host" + http: + paths: + - backend: + service: + name: "test-service" + port: + number: 80 + path: / + pathType: Prefix + tls: + - hosts: + - "host" + secretName: "keyvault-test-service" \ No newline at end of file diff --git a/pkg/fixtures/addons/kustomize/ingress.yaml b/pkg/fixtures/addons/kustomize/ingress.yaml new file mode 100644 index 00000000..b4d05333 --- /dev/null +++ b/pkg/fixtures/addons/kustomize/ingress.yaml @@ -0,0 +1,33 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.azure.com/tls-cert-keyvault-uri: "test.uri" + kubernetes.azure.com/use-osm-mtls: "false" + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + nginx.ingress.kubernetes.io/configuration-snippet: |2- + + proxy_ssl_name "default.test-namespace.cluster.local"; + nginx.ingress.kubernetes.io/proxy-ssl-secret: kube-system/osm-ingress-client-cert + nginx.ingress.kubernetes.io/proxy-ssl-verify: "on" + name: "test-service" + namespace: "test-namespace" + labels: + kubernetes.azure.com/generator: draft +spec: + ingressClassName: webapprouting.kubernetes.azure.com + rules: + - host: "host" + http: + paths: + - backend: + service: + name: "test-service" + port: + number: 80 + path: / + pathType: Prefix + tls: + - hosts: + - "host" + secretName: "keyvault-test-service" \ No newline at end of file diff --git a/pkg/fixtures/deployments/charts/.helmignore b/pkg/fixtures/deployments/charts/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/pkg/fixtures/deployments/charts/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/pkg/fixtures/deployments/charts/Chart.yaml b/pkg/fixtures/deployments/charts/Chart.yaml new file mode 100644 index 00000000..0462171f --- /dev/null +++ b/pkg/fixtures/deployments/charts/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: testapp +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/pkg/fixtures/deployments/charts/production.yaml b/pkg/fixtures/deployments/charts/production.yaml new file mode 100644 index 00000000..d3391779 --- /dev/null +++ b/pkg/fixtures/deployments/charts/production.yaml @@ -0,0 +1,8 @@ +image: + repository: "testapp" + pullPolicy: Always + tag: "latest" +service: + annotations: {} + type: LoadBalancer + port: "80" diff --git a/pkg/fixtures/deployments/charts/templates/_helpers.tpl b/pkg/fixtures/deployments/charts/templates/_helpers.tpl new file mode 100644 index 00000000..276b51f5 --- /dev/null +++ b/pkg/fixtures/deployments/charts/templates/_helpers.tpl @@ -0,0 +1,39 @@ + +{{- define "testapp.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + + +{{- define "testapp.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + + +{{- define "testapp.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + + +{{- define "testapp.labels" -}} +helm.sh/chart: {{ include "testapp.chart" . }} +{{ include "testapp.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + + +{{- define "testapp.selectorLabels" -}} +app.kubernetes.io/name: {{ include "testapp.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/pkg/fixtures/deployments/charts/templates/deployment.yaml b/pkg/fixtures/deployments/charts/templates/deployment.yaml new file mode 100644 index 00000000..ec61f72c --- /dev/null +++ b/pkg/fixtures/deployments/charts/templates/deployment.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "testapp.fullname" . }} + labels: + {{- include "testapp.labels" . | nindent 4 }} + kubernetes.azure.com/generator: {{ .Values.generatorLabel }} + namespace: {{ .Values.namespace }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "testapp.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "testapp.selectorLabels" . | nindent 8 }} + namespace: {{ .Values.namespace }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.containerPort }} + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/pkg/fixtures/deployments/charts/templates/service.yaml b/pkg/fixtures/deployments/charts/templates/service.yaml new file mode 100644 index 00000000..72b9c183 --- /dev/null +++ b/pkg/fixtures/deployments/charts/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "testapp.fullname" . }} + labels: + {{- include "testapp.labels" . | nindent 4 }} + kubernetes.azure.com/generator: {{.Values.generatorLabel}} + annotations: + {{ toYaml .Values.service.annotations | nindent 4 }} + namespace: {{ .Values.namespace }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.containerPort }} + protocol: TCP + name: svchttp + selector: + {{- include "testapp.selectorLabels" . | nindent 6 }} diff --git a/pkg/fixtures/deployments/charts/values.yaml b/pkg/fixtures/deployments/charts/values.yaml new file mode 100644 index 00000000..c22ff16e --- /dev/null +++ b/pkg/fixtures/deployments/charts/values.yaml @@ -0,0 +1,63 @@ +# Default values for testapp. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 + +namespace: default + +containerPort: 80 + +image: + repository: testimage + tag: latest + pullPolicy: Always + + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +podAnnotations: {} + +podSecurityContext: {} +# fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true +# runAsUser: 1000 + +service: + annotations: {} + type: LoadBalancer + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m +# memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +generatorLabel: draft \ No newline at end of file diff --git a/pkg/fixtures/pipelines/kustomize.yaml b/pkg/fixtures/pipelines/kustomize.yaml new file mode 100644 index 00000000..ae60918f --- /dev/null +++ b/pkg/fixtures/pipelines/kustomize.yaml @@ -0,0 +1,68 @@ +# Azure Kubernetes Service (AKS) pipeline with Kustomize +# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service cluster + +variables: + armServiceConnection: testServiceConnection + azureContainerRegistry: testACR + containerName: testContainer + acrRg: testACRRG + clusterRg: testRG + clusterName: testCluster + kustomizePath: kustomize/overlays/production + namespace: testNamespace + tag: "$(Build.BuildId)" + vmImageName: "ubuntu-latest" + +trigger: + - main + +name: testPipeline + +stages: + - stage: BuildAndPush + displayName: Build stage + jobs: + - job: BuildAndPush + displayName: Build and push image + pool: + vmImage: $(vmImageName) + steps: + - task: AzureCLI@2 + displayName: Build and push image to Azure Container Registry + inputs: + azureSubscription: $(armServiceConnection) + scriptType: "bash" + scriptLocation: "inlineScript" + inlineScript: | + az acr build --image $1.azurecr.io/$2:$3 --registry $1 -g $4 . + arguments: "$(azureContainerRegistry) $(containerName) $(tag) $(acrRg)" + + - stage: Deploy + displayName: Deploy stage + dependsOn: BuildAndPush + jobs: + - job: Deploy + displayName: Deploy to AKS using Kustomize + pool: + vmImage: $(vmImageName) + steps: + - task: KubernetesManifest@1 + displayName: Bake Kustomize manifests + inputs: + action: 'bake' + kustomizationPath: $(kustomizePath) + renderType: 'kustomize' + name: 'bake' + + - task: KubernetesManifest@1 + displayName: Deploy baked manifests to Kubernetes cluster + inputs: + action: 'deploy' + connectionType: 'azureResourceManager' + azureSubscriptionConnection: $(armServiceConnection) + azureResourceGroup: $(clusterRg) + kubernetesCluster: $(clusterName) + namespace: $(namespace) + manifests: $(bake.manifestsBundle) + containers: | + $(azureContainerRegistry).azurecr.io/$(containerName):$(tag) diff --git a/pkg/fixtures/pipelines/manifests.yaml b/pkg/fixtures/pipelines/manifests.yaml new file mode 100644 index 00000000..754cef97 --- /dev/null +++ b/pkg/fixtures/pipelines/manifests.yaml @@ -0,0 +1,60 @@ +# Azure Kubernetes Service pipeline +# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service cluster + +variables: + armServiceConnection: testServiceConnection + azureContainerRegistry: testACR + containerName: testContainer + clusterRg: testRG + acrRg: testACRRG + clusterName: testCluster + manifestPath: test/manifests + namespace: testNamespace + tag: "$(Build.BuildId)" + vmImageName: "ubuntu-latest" + +name: testPipeline + +trigger: + - main + +stages: + - stage: BuildAndPush + displayName: Build stage + jobs: + - job: BuildAndPush + displayName: Build and push image + pool: + vmImage: $(vmImageName) + steps: + - task: AzureCLI@2 + displayName: Build and push image to Azure Container Registry + inputs: + azureSubscription: $(armServiceConnection) + scriptType: "bash" + scriptLocation: "inlineScript" + inlineScript: | + az acr build --image $1.azurecr.io/$2:$3 --registry $1 -g $4 . + arguments: "$(azureContainerRegistry) $(containerName) $(tag) $(acrRg)" + + - stage: Deploy + displayName: Deploy stage + dependsOn: BuildAndPush + jobs: + - job: Deploy + displayName: Deploy to AKS + pool: + vmImage: $(vmImageName) + steps: + - task: KubernetesManifest@1 + displayName: Deploy to Kubernetes cluster + inputs: + action: "deploy" + connectionType: "azureResourceManager" + azureSubscriptionConnection: $(armServiceConnection) + azureResourceGroup: $(clusterRg) + kubernetesCluster: $(clusterName) + manifests: $(manifestPath) + namespace: $(namespace) + containers: | + $(azureContainerRegistry).azurecr.io/$(containerName):$(tag) diff --git a/pkg/fixtures/validatetemplate.go b/pkg/fixtures/validatetemplate.go new file mode 100644 index 00000000..a2c4616a --- /dev/null +++ b/pkg/fixtures/validatetemplate.go @@ -0,0 +1,40 @@ +package fixtures + +import ( + "embed" + "errors" + "fmt" + "os" + "regexp" + "strings" +) + +//go:embed pipelines/* +var pipelines embed.FS + +//go:embed deployments/* +var deployments embed.FS + +func ValidateContentAgainstFixture(generatedContent []byte, fixturePath string) error { + fullFixturePath := fmt.Sprintf("%s", fixturePath) + + // Read the fixture content + fixtureContent, err := os.ReadFile(fullFixturePath) + if err != nil { + return fmt.Errorf("failed to read fixture: %w", err) + } + + if normalizeWhitespace(fixtureContent) != normalizeWhitespace(generatedContent) { + return errors.New("generated content does not match fixture") + } + + return nil +} + +func normalizeWhitespace(content []byte) string { + s := string(content) + re := regexp.MustCompile(`\r?\n`) + s = re.ReplaceAllString(s, "\n") + re = regexp.MustCompile(`\s+`) + return strings.TrimSpace(re.ReplaceAllString(s, " ")) +} diff --git a/pkg/fixtures/workflows/azure-kubernetes-service-helm.yml b/pkg/fixtures/workflows/azure-kubernetes-service-helm.yml new file mode 100644 index 00000000..8d57e78d --- /dev/null +++ b/pkg/fixtures/workflows/azure-kubernetes-service-helm.yml @@ -0,0 +1,135 @@ +# 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 == '' + 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/azure-kubernetes-service-kustomize.yml new file mode 100644 index 00000000..ee198518 --- /dev/null +++ b/pkg/fixtures/workflows/azure-kubernetes-service-kustomize.yml @@ -0,0 +1,139 @@ +# 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) +# - NAMESPACE (namespace to deploy your application) +# +# 3. Choose the appropriate render engine for the bake step https://github.com/Azure/k8s-bake. The config below assumes Kustomize. +# Set your kustomizationPath and kubectl-version to suit your configuration. +# - KUSTOMIZE_PATH (the path where your Kustomize manifests are located) +# +# 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 + KUSTOMIZE_PATH: ./overlays/production + DOCKER_FILE: ./Dockerfile + BUILD_CONTEXT_PATH: test + 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.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ 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' + + # Runs Kustomize to create manifest files + - name: Bake deployment + uses: azure/k8s-bake@v2 + with: + renderEngine: "kustomize" + kustomizationPath: ${{ env.KUSTOMIZE_PATH }} + kubectl-version: latest + id: bake + + # 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 based on manifest files from previous step + - name: Deploy application + uses: Azure/k8s-deploy@v4 + with: + action: deploy + manifests: ${{ steps.bake.outputs.manifestsBundle }} + images: | + ${{ env.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ env.CONTAINER_NAME }}:${{ github.sha }} + resource-group: ${{ env.CLUSTER_RESOURCE_GROUP }} + name: ${{ env.CLUSTER_NAME }} + private-cluster: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' }} + namespace: ${{ env.NAMESPACE }} + diff --git a/pkg/fixtures/workflows/azure-kubernetes-service.yml b/pkg/fixtures/workflows/azure-kubernetes-service.yml new file mode 100644 index 00000000..92c2dbff --- /dev/null +++ b/pkg/fixtures/workflows/azure-kubernetes-service.yml @@ -0,0 +1,125 @@ +# 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 can be found at 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) +# - CLUSTER_RESOURCE_GROUP (where your cluster is deployed) +# - CLUSTER_NAME (name of your AKS cluster) +# - CONTAINER_NAME (name of the container image you would like to push up to your ACR) +# - DEPLOYMENT_MANIFEST_PATH (path to the manifest yaml for your deployment) +# - DOCKER_FILE (path to your Dockerfile) +# - BUILD_CONTEXT_PATH (path to the context of your Dockerfile) +# - 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 + DEPLOYMENT_MANIFEST_PATH: ./manifests + DOCKER_FILE: ./Dockerfile + BUILD_CONTEXT_PATH: test + 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.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ 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 based on given manifest file + - name: Deploys application + uses: Azure/k8s-deploy@v4 + with: + action: deploy + manifests: ${{ env.DEPLOYMENT_MANIFEST_PATH }} + images: | + ${{ env.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ env.CONTAINER_NAME }}:${{ github.sha }} + resource-group: ${{ env.CLUSTER_RESOURCE_GROUP }} + name: ${{ env.CLUSTER_NAME }} + private-cluster: ${{ steps.isPrivate.outputs.PRIVATE_CLUSTER == 'true' }} + namespace: ${{ env.NAMESPACE }} diff --git a/pkg/languages/languages.go b/pkg/languages/languages.go index 53e03255..f563012c 100644 --- a/pkg/languages/languages.go +++ b/pkg/languages/languages.go @@ -53,7 +53,7 @@ func (l *Languages) CreateDockerfileForLanguage(lang string, langConfig *config. return fmt.Errorf("create dockerfile for language: %w", err) } - if err := osutil.CopyDir(l.dockerfileTemplates, srcDir, l.dest, langConfig, templateWriter); err != nil { + if err := osutil.CopyDirWithTemplates(l.dockerfileTemplates, srcDir, l.dest, langConfig, templateWriter); err != nil { return err } diff --git a/pkg/workflows/workflows_test.go b/pkg/workflows/workflows_test.go index 30dcabf6..1008a09f 100644 --- a/pkg/workflows/workflows_test.go +++ b/pkg/workflows/workflows_test.go @@ -3,6 +3,10 @@ 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" @@ -10,15 +14,11 @@ import ( "testing" "testing/fstest" - appsv1 "k8s.io/api/apps/v1" - "k8s.io/client-go/kubernetes/scheme" - + "github.com/Azure/draft/template" "github.com/stretchr/testify/assert" - "github.com/Azure/draft/pkg/config" - "github.com/Azure/draft/pkg/embedutils" - "github.com/Azure/draft/pkg/templatewriter/writers" - "github.com/Azure/draft/template" + appsv1 "k8s.io/api/apps/v1" + "k8s.io/client-go/kubernetes/scheme" ) func TestCreateWorkflows(t *testing.T) { @@ -160,6 +160,8 @@ func TestCreateWorkflows(t *testing.T) { tempDirPath string tempFileName string tempPath string + expectedFile string + fixturePath string cleanUp func() }{ { @@ -169,6 +171,8 @@ func TestCreateWorkflows(t *testing.T) { 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") @@ -181,6 +185,8 @@ func TestCreateWorkflows(t *testing.T) { 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") @@ -193,6 +199,8 @@ func TestCreateWorkflows(t *testing.T) { 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") @@ -232,11 +240,21 @@ func TestCreateWorkflows(t *testing.T) { 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() }) } diff --git a/template/addons/azure/webapp_routing/draft.yaml b/template/addons/azure/webapp_routing/draft.yaml index 0e5e9dc2..ec8e8bf7 100644 --- a/template/addons/azure/webapp_routing/draft.yaml +++ b/template/addons/azure/webapp_routing/draft.yaml @@ -1,13 +1,23 @@ +templateName: "app-routing-ingress" +description: "This template is used to create an ingress resource for use with the app-routing addon in AKS" +type: "manifest" variables: - name: "ingress-tls-cert-keyvault-uri" + type: "string" + kind: "azureKeyvaultUri" description: "the keyvault uri for the tls certificate" - name: "ingress-use-osm-mtls" description: "use open service mesh mutual-tls" type: "bool" + kind: "flag" - name: "ingress-host" + type: "string" + kind: "ingressHostName" description: "specify the host of the ingress resource" - name: "GENERATORLABEL" - default: + type: "string" + kind: "label" + default: disablePrompt: true value: "draft" description: "the label to identify who generated the resource" @@ -18,4 +28,4 @@ references: - name: "service-port" path: "spec.ports.port" - name: "service-namespace" - path: "metadata.namespace" \ No newline at end of file + path: "metadata.namespace" diff --git a/template/addons/azure/webapp_routing/ingress.yaml b/template/addons/azure/webapp_routing/ingress.yaml index e2d32796..c230c138 100644 --- a/template/addons/azure/webapp_routing/ingress.yaml +++ b/template/addons/azure/webapp_routing/ingress.yaml @@ -2,32 +2,32 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.azure.com/tls-cert-keyvault-uri: "{{ingress-tls-cert-keyvault-uri}}" - kubernetes.azure.com/use-osm-mtls: "{{ingress-use-osm-mtls}}" + kubernetes.azure.com/tls-cert-keyvault-uri: "{{index . "ingress-tls-cert-keyvault-uri"}}" + kubernetes.azure.com/use-osm-mtls: "{{index . "ingress-use-osm-mtls"}}" nginx.ingress.kubernetes.io/backend-protocol: HTTPS nginx.ingress.kubernetes.io/configuration-snippet: |2- - proxy_ssl_name "default.{{service-namespace}}.cluster.local"; + proxy_ssl_name "default.{{index . "service-namespace"}}.cluster.local"; nginx.ingress.kubernetes.io/proxy-ssl-secret: kube-system/osm-ingress-client-cert nginx.ingress.kubernetes.io/proxy-ssl-verify: "on" - name: {{service-name}} - namespace: {{service-namespace}} + name: "{{index . "service-name"}}" + namespace: "{{index . "service-namespace"}}" labels: - kubernetes.azure.com/generator: {{GENERATORLABEL}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} spec: ingressClassName: webapprouting.kubernetes.azure.com rules: - - host: {{ingress-host}} - http: - paths: - - backend: - service: - name: {{service-name}} - port: - number: {{service-port}} - path: / - pathType: Prefix + - host: "{{index . "ingress-host"}}" + http: + paths: + - backend: + service: + name: "{{index . "service-name"}}" + port: + number: {{index . "service-port"}} + path: / + pathType: Prefix tls: - - hosts: - - {{ingress-host}} - secretName: keyvault-{{service-name}} \ No newline at end of file + - hosts: + - "{{index . "ingress-host"}}" + secretName: "keyvault-{{index . "service-name"}}" \ No newline at end of file diff --git a/template/azurePipelines/kustomize/.pipelines/azure-kubernetes-service.yaml b/template/azurePipelines/kustomize/.pipelines/azure-kubernetes-service.yaml index 11f12daa..f307aaed 100644 --- a/template/azurePipelines/kustomize/.pipelines/azure-kubernetes-service.yaml +++ b/template/azurePipelines/kustomize/.pipelines/azure-kubernetes-service.yaml @@ -2,22 +2,22 @@ # Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service cluster variables: - armServiceConnection: {{ARMSERVICECONNECTION}} - azureContainerRegistry: {{AZURECONTAINERREGISTRY}} - containerName: {{CONTAINERNAME}} - acrRg: {{CLUSTERRESOURCEGROUP}} - clusterRg: {{ACRRESOURCEGROUP}} - clusterName: {{CLUSTERNAME}} - kustomizePath: {{KUSTOMIZEPATH}} - namespace: {{NAMESPACE}} + armServiceConnection: {{.ARMSERVICECONNECTION}} + azureContainerRegistry: {{.AZURECONTAINERREGISTRY}} + containerName: {{.CONTAINERNAME}} + acrRg: {{.ACRRESOURCEGROUP}} + clusterRg: {{.CLUSTERRESOURCEGROUP}} + clusterName: {{.CLUSTERNAME}} + kustomizePath: {{.KUSTOMIZEPATH}} + namespace: {{.NAMESPACE}} tag: "$(Build.BuildId)" vmImageName: "ubuntu-latest" trigger: - - {{BRANCHNAME}} - -name: {{PIPELINENAME}} + - {{.BRANCHNAME}} +name: {{.PIPELINENAME}} +{{` stages: - stage: BuildAndPush displayName: Build stage @@ -65,4 +65,5 @@ stages: namespace: $(namespace) manifests: $(bake.manifestsBundle) containers: | - $(azureContainerRegistry).azurecr.io/$(containerName):$(tag) \ No newline at end of file + $(azureContainerRegistry).azurecr.io/$(containerName):$(tag) +`}} \ No newline at end of file diff --git a/template/azurePipelines/kustomize/draft.yaml b/template/azurePipelines/kustomize/draft.yaml index d1d230f6..3c81762e 100644 --- a/template/azurePipelines/kustomize/draft.yaml +++ b/template/azurePipelines/kustomize/draft.yaml @@ -1,30 +1,53 @@ +templateName: "azure-pipeline-kustomize" +description: "This template is used to create an Azure Pipeline for deploying an app to AKS using Kustomize" +type: "workflow" variables: - name: "PIPELINENAME" + type: "string" + kind: "workflowName" default: value: "Build and deploy an app to AKS" description: "the name of the azure pipeline" - name: "BRANCHNAME" + type: "string" + kind: "repositoryBranch" default: value: "main" description: "the branch to trigger the pipeline" - name: "ARMSERVICECONNECTION" + type: "string" + kind: "azureServiceConnection" description: "the name of the Azure Resource Manager service connection" - name: "AZURECONTAINERREGISTRY" + type: "string" + kind: "azureContainerRegistry" description: "the name of the Azure Container Registry" - name: "CONTAINERNAME" + type: "string" + kind: "containerImageName" description: "the container image name" - name: "CLUSTERRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the AKS cluster resource group" - name: "ACRRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the ACR resource group" - name: "CLUSTERNAME" + type: "string" + kind: "azureManagedCluster" description: "the AKS cluster name" - name: "KUSTOMIZEPATH" + type: "string" + kind: "dirPath" default: disablePrompt: true value: "./overlays/production" # keeping this as default since draft generates the manifests in the overlays/production directory description: "the path to the Kustomize directory" - name: "NAMESPACE" + type: "string" + kind: "kubernetesNamespace" default: value: "default" - description: "the Kubernetes namespace" \ No newline at end of file + description: "the Kubernetes namespace" diff --git a/template/azurePipelines/manifests/.pipelines/azure-kubernetes-service.yaml b/template/azurePipelines/manifests/.pipelines/azure-kubernetes-service.yaml index 45c06f8f..10ef1d38 100644 --- a/template/azurePipelines/manifests/.pipelines/azure-kubernetes-service.yaml +++ b/template/azurePipelines/manifests/.pipelines/azure-kubernetes-service.yaml @@ -2,22 +2,22 @@ # Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service cluster variables: - armServiceConnection: {{ARMSERVICECONNECTION}} - azureContainerRegistry: {{AZURECONTAINERREGISTRY}} - containerName: {{CONTAINERNAME}} - clusterRg: {{CLUSTERRESOURCEGROUP}} - acrRg: {{ACRRESOURCEGROUP}} - clusterName: {{CLUSTERNAME}} - manifestPath: {{MANIFESTPATH}} - namespace: {{NAMESPACE}} + armServiceConnection: {{.ARMSERVICECONNECTION}} + azureContainerRegistry: {{.AZURECONTAINERREGISTRY}} + containerName: {{.CONTAINERNAME}} + clusterRg: {{.CLUSTERRESOURCEGROUP}} + acrRg: {{.ACRRESOURCEGROUP}} + clusterName: {{.CLUSTERNAME}} + manifestPath: {{.MANIFESTPATH}} + namespace: {{.NAMESPACE}} tag: "$(Build.BuildId)" vmImageName: "ubuntu-latest" -name: {{PIPELINENAME}} +name: {{.PIPELINENAME}} trigger: - - {{BRANCHNAME}} - + - {{.BRANCHNAME}} +{{` stages: - stage: BuildAndPush displayName: Build stage @@ -58,3 +58,4 @@ stages: namespace: $(namespace) containers: | $(azureContainerRegistry).azurecr.io/$(containerName):$(tag) +`}} \ No newline at end of file diff --git a/template/azurePipelines/manifests/draft.yaml b/template/azurePipelines/manifests/draft.yaml index bcb0b015..b124e0bb 100644 --- a/template/azurePipelines/manifests/draft.yaml +++ b/template/azurePipelines/manifests/draft.yaml @@ -1,30 +1,53 @@ +templateName: "azure-pipeline-manifest" +description: "Azure Pipeline for deploying a containerized application to AKS using kubernetes manifests" +type: "workflow" variables: - name: "PIPELINENAME" + type: "string" + kind: "workflowName" default: value: "Build and deploy an app to AKS" description: "the name of the azure pipeline" - name: "BRANCHNAME" + type: "string" + kind: "repositoryBranch" default: value: "main" description: "the branch to trigger the pipeline" - name: "ARMSERVICECONNECTION" + type: "string" + kind: "azureServiceConnection" description: "the name of the Azure Resource Manager service connection" - name: "AZURECONTAINERREGISTRY" + type: "string" + kind: "azureContainerRegistry" description: "the name of the Azure Container Registry" - name: "CONTAINERNAME" + type: "string" + kind: "containerImageName" description: "the container image name" - name: "CLUSTERRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the AKS cluster resource group" - name: "ACRRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the ACR resource group" - name: "CLUSTERNAME" + type: "string" + kind: "azureManagedCluster" description: "the AKS cluster name" - name: "MANIFESTPATH" + type: "string" + kind: "dirPath" default: disablePrompt: true value: "./manifests" description: "the path to the Kubernetes deployment manifest" - name: "NAMESPACE" + type: "string" + kind: "kubernetesNamespace" default: value: "default" - description: "the Kubernetes namespace" \ No newline at end of file + description: "the Kubernetes namespace" diff --git a/template/deployments/helm/charts/Chart.yaml b/template/deployments/helm/charts/Chart.yaml index b26c2ea9..4480aa68 100644 --- a/template/deployments/helm/charts/Chart.yaml +++ b/template/deployments/helm/charts/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -name: {{APPNAME}} +name: {{.APPNAME}} description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart. diff --git a/template/deployments/helm/charts/production.yaml b/template/deployments/helm/charts/production.yaml index 92d65a30..36e67ec8 100644 --- a/template/deployments/helm/charts/production.yaml +++ b/template/deployments/helm/charts/production.yaml @@ -1,8 +1,8 @@ image: - repository: "{{APPNAME}}" + repository: "{{.APPNAME}}" pullPolicy: Always tag: "latest" service: annotations: {} type: LoadBalancer - port: "{{SERVICEPORT}}" + port: "{{.SERVICEPORT}}" diff --git a/template/deployments/helm/charts/templates/_helpers.tpl b/template/deployments/helm/charts/templates/_helpers.tpl index 5298b547..30222bcc 100644 --- a/template/deployments/helm/charts/templates/_helpers.tpl +++ b/template/deployments/helm/charts/templates/_helpers.tpl @@ -1,17 +1,17 @@ {{/* Expand the name of the chart. */}} -{{- define "{{APPNAME}}.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} +{{ printf "{{- define \"%s.name\" -}}" .APPNAME }} +{{`{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }}`}} {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "{{APPNAME}}.fullname" -}} -{{- if .Values.fullnameOverride }} +{{ printf "{{- define \"%s.fullname\" -}}" .APPNAME }} +{{`{{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} @@ -21,31 +21,29 @@ If release name contains chart name it will be used as a full name. {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} -{{- end }} +{{- end }}`}} {{/* Create chart name and version as used by the chart label. */}} -{{- define "{{APPNAME}}.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} +{{ printf "{{- define \"%s.chart\" -}}" .APPNAME }} +{{`{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }}`}} {{/* Common labels */}} -{{- define "{{APPNAME}}.labels" -}} -helm.sh/chart: {{ include "{{APPNAME}}.chart" . }} -{{ include "{{APPNAME}}.selectorLabels" . }} -{{- if .Chart.AppVersion }} +{{ printf "{{- define \"%s.labels\" -}}" .APPNAME }} +helm.sh/chart: {{ printf "{{ include \"%s.chart\" . }}" .APPNAME }} +{{ printf "{{ include \"%s.selectorLabels\" . }}" .APPNAME }} +{{`{{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} +{{- end }}`}} {{/* Selector labels */}} -{{- define "{{APPNAME}}.selectorLabels" -}} -app.kubernetes.io/name: {{ include "{{APPNAME}}.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} \ No newline at end of file +{{ printf "{{- define \"%s.selectorLabels\" -}}" .APPNAME }} +{{ printf "app.kubernetes.io/name: {{ include \"%s.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}" .APPNAME }} \ No newline at end of file diff --git a/template/deployments/helm/charts/templates/deployment.yaml b/template/deployments/helm/charts/templates/deployment.yaml index e1b38e17..dd1537e0 100644 --- a/template/deployments/helm/charts/templates/deployment.yaml +++ b/template/deployments/helm/charts/templates/deployment.yaml @@ -1,28 +1,35 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "{{APPNAME}}.fullname" . }} + name: {{ printf "{{ include \"%s.fullname\" . }}" .APPNAME }} labels: - {{- include "{{APPNAME}}.labels" . | nindent 4 }} - kubernetes.azure.com/generator: {{GENERATORLABEL}} + {{ printf "{{- include \"%s.labels\" . | nindent 4 }}" .APPNAME }} + {{- ` + kubernetes.azure.com/generator: {{ .Values.generatorLabel }} namespace: {{ .Values.namespace }} +` -}} spec: +{{- ` {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} - {{- end }} + {{- end }} + ` -}} selector: matchLabels: - {{- include "{{APPNAME}}.selectorLabels" . | nindent 6 }} + {{ printf "{{- include \"%s.selectorLabels\" . | nindent 6 }}" .APPNAME }} template: - metadata: + metadata: + {{- ` {{- with .Values.podAnnotations }} annotations: {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} + ` -}} labels: - {{- include "{{APPNAME}}.selectorLabels" . | nindent 8 }} - namespace: {{ .Values.namespace }} - spec: + {{ printf "{{- include \"%s.selectorLabels\" . | nindent 8 }}" .APPNAME }} + namespace: {{ print "{{ .Values.namespace }}" }} + spec: + {{- ` {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -61,3 +68,4 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} +` -}} \ No newline at end of file diff --git a/template/deployments/helm/charts/templates/service.yaml b/template/deployments/helm/charts/templates/service.yaml index 9ef0293f..5bc87795 100644 --- a/template/deployments/helm/charts/templates/service.yaml +++ b/template/deployments/helm/charts/templates/service.yaml @@ -1,19 +1,23 @@ apiVersion: v1 kind: Service metadata: - name: {{ include "{{APPNAME}}.fullname" . }} + name: {{ printf "{{ include \"%s.fullname\" . }}" .APPNAME }} labels: - {{- include "{{APPNAME}}.labels" . | nindent 4 }} - kubernetes.azure.com/generator: {{GENERATORLABEL}} + {{ printf "{{- include \"%s.labels\" . | nindent 4 }}" .APPNAME }} + {{- ` + kubernetes.azure.com/generator: {{.Values.generatorLabel}} annotations: {{ toYaml .Values.service.annotations | nindent 4 }} namespace: {{ .Values.namespace }} +` -}} spec: +{{- ` type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} targetPort: {{ .Values.containerPort }} protocol: TCP name: svchttp + ` -}} selector: - {{- include "{{APPNAME}}.selectorLabels" . | nindent 4 }} + {{ printf "{{- include \"%s.selectorLabels\" . | nindent 6 }}" .APPNAME }} diff --git a/template/deployments/helm/charts/values.yaml b/template/deployments/helm/charts/values.yaml index 4e0d08d4..321227f8 100644 --- a/template/deployments/helm/charts/values.yaml +++ b/template/deployments/helm/charts/values.yaml @@ -1,16 +1,15 @@ -# Default values for {{APPNAME}}. +# Default values for {{.APPNAME}}. # This is a YAML-formatted file. # Declare variables to be passed into your templates. - replicaCount: 1 -namespace: {{NAMESPACE}} +namespace: {{.NAMESPACE}} -containerPort: {{PORT}} +containerPort: {{.PORT}} image: - repository: {{IMAGENAME}} - tag: {{IMAGETAG}} + repository: {{.IMAGENAME}} + tag: {{.IMAGETAG}} pullPolicy: Always @@ -34,7 +33,7 @@ securityContext: {} service: annotations: {} type: LoadBalancer - port: {{SERVICEPORT}} + port: {{.SERVICEPORT}} resources: {} # We usually recommend not to specify default resources and to leave this as a conscious @@ -60,3 +59,5 @@ nodeSelector: {} tolerations: [] affinity: {} + +generatorLabel: {{.GENERATORLABEL}} \ No newline at end of file diff --git a/template/deployments/helm/draft.yaml b/template/deployments/helm/draft.yaml index 7faf524d..eaae9017 100644 --- a/template/deployments/helm/draft.yaml +++ b/template/deployments/helm/draft.yaml @@ -1,29 +1,46 @@ +templateName: "deployment-helm" +description: "This template is used to create a Helm deployment for an application" +type: "deployment" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: 80 description: "the port exposed in the application" - name: "APPNAME" + type: "string" + kind: "kubernetesResourceName" description: "the name of the application" - name: "SERVICEPORT" + type: "int" + kind: "port" default: referenceVar: "PORT" description: "the port the service uses to make the application accessible from outside the cluster" - name: "NAMESPACE" - default: + type: "string" + kind: "kubernetesNamespace" + default: value: default description: " the namespace to place new resources in" - name: "IMAGENAME" + type: "string" + kind: "containerImageName" default: referenceVar: "APPNAME" description: "the name of the image to use in the deployment" - name: "IMAGETAG" - default: + type: "string" + kind: "containerImageVersion" + default: disablePrompt: true value: "latest" description: "the tag of the image to use in the deployment" - name: "GENERATORLABEL" - default: - disablePrompt: true + type: "string" + kind: "label" + default: + disablePrompt: true value: "draft" - description: "the label to identify who generated the resource" \ No newline at end of file + description: "the label to identify who generated the resource" diff --git a/template/deployments/kustomize/base/deployment.yaml b/template/deployments/kustomize/base/deployment.yaml index 9b406898..4e07bd64 100644 --- a/template/deployments/kustomize/base/deployment.yaml +++ b/template/deployments/kustomize/base/deployment.yaml @@ -1,24 +1,24 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{APPNAME}} + name: {{.APPNAME}} labels: - app: {{APPNAME}} - kubernetes.azure.com/generator: {{GENERATORLABEL}} - namespace: {{NAMESPACE}} + app: {{.APPNAME}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} + namespace: {{.NAMESPACE}} spec: replicas: 1 selector: matchLabels: - app: {{APPNAME}} + app: {{.APPNAME}} template: metadata: labels: - app: {{APPNAME}} + app: {{.APPNAME}} spec: containers: - - name: {{APPNAME}} - image: {{IMAGENAME}}:{{IMAGETAG}} + - name: {{.APPNAME}} + image: {{.IMAGENAME}}:{{.IMAGETAG}} imagePullPolicy: Always ports: - - containerPort: {{PORT}} + - containerPort: {{.PORT}} \ No newline at end of file diff --git a/template/deployments/kustomize/base/namespace.yaml b/template/deployments/kustomize/base/namespace.yaml index c0c9c3f5..76a4a407 100644 --- a/template/deployments/kustomize/base/namespace.yaml +++ b/template/deployments/kustomize/base/namespace.yaml @@ -1,6 +1,6 @@ kind: Namespace apiVersion: v1 metadata: - name: {{NAMESPACE}} + name: {{.NAMESPACE}} labels: - kubernetes.azure.com/generator: {{GENERATORLABEL}} \ No newline at end of file + kubernetes.azure.com/generator: {{.GENERATORLABEL}} \ No newline at end of file diff --git a/template/deployments/kustomize/base/service.yaml b/template/deployments/kustomize/base/service.yaml index e99c7f41..83481aa4 100644 --- a/template/deployments/kustomize/base/service.yaml +++ b/template/deployments/kustomize/base/service.yaml @@ -1,15 +1,15 @@ apiVersion: v1 kind: Service metadata: - name: {{APPNAME}} - namespace: {{NAMESPACE}} + name: {{.APPNAME}} + namespace: {{.NAMESPACE}} labels: - kubernetes.azure.com/generator: {{GENERATORLABEL}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} spec: type: LoadBalancer selector: - app: {{APPNAME}} + app: {{.APPNAME}} ports: - protocol: TCP - port: {{SERVICEPORT}} - targetPort: {{PORT}} \ No newline at end of file + port: {{.SERVICEPORT}} + targetPort: {{.PORT}} \ No newline at end of file diff --git a/template/deployments/kustomize/draft.yaml b/template/deployments/kustomize/draft.yaml index 6b27b237..d8b79d0d 100644 --- a/template/deployments/kustomize/draft.yaml +++ b/template/deployments/kustomize/draft.yaml @@ -1,29 +1,46 @@ +templateName: "deployment-kustomize" +description: "This template is used to create a Kustomize deployment for an application" +type: "deployment" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: 80 description: "the port exposed in the application" - name: "APPNAME" + type: "string" + kind: "kubernetesResourceName" description: "the name of the application" - name: "SERVICEPORT" + type: "int" + kind: "port" default: referenceVar: "PORT" description: "the port the service uses to make the application accessible from outside the cluster" - name: "NAMESPACE" - default: + type: "string" + kind: "kubernetesNamespace" + default: value: default description: " the namespace to place new resources in" - name: "IMAGENAME" + type: "string" + kind: "containerImageName" default: referenceVar: "APPNAME" description: "the name of the image to use in the deployment" - name: "IMAGETAG" + type: "string" + kind: "containerImageVersion" default: - disablePrompt: true + disablePrompt: true value: "latest" description: "the tag of the image to use in the deployment" - name: "GENERATORLABEL" - default: + type: "string" + kind: "label" + default: disablePrompt: true value: "draft" - description: "the label to identify who generated the resource" \ No newline at end of file + description: "the label to identify who generated the resource" diff --git a/template/deployments/kustomize/overlays/production/deployment.yaml b/template/deployments/kustomize/overlays/production/deployment.yaml index 6d93337e..0929b145 100644 --- a/template/deployments/kustomize/overlays/production/deployment.yaml +++ b/template/deployments/kustomize/overlays/production/deployment.yaml @@ -1,17 +1,17 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{APPNAME}} + name: {{.APPNAME}} labels: - app: {{APPNAME}} - kubernetes.azure.com/generator: {{GENERATORLABEL}} - namespace: {{NAMESPACE}} + app: {{.APPNAME}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} + namespace: {{.NAMESPACE}} spec: selector: matchLabels: - app: {{APPNAME}} + app: {{.APPNAME}} template: spec: containers: - - name: {{APPNAME}} - image: {{IMAGENAME}}:{{IMAGETAG}} \ No newline at end of file + - name: {{.APPNAME}} + image: {{.IMAGENAME}}:{{.IMAGETAG}} \ No newline at end of file diff --git a/template/deployments/kustomize/overlays/production/kustomization.yaml b/template/deployments/kustomize/overlays/production/kustomization.yaml index 456210a1..d13c9cee 100644 --- a/template/deployments/kustomize/overlays/production/kustomization.yaml +++ b/template/deployments/kustomize/overlays/production/kustomization.yaml @@ -1,5 +1,5 @@ namePrefix: production- -namespace: {{NAMESPACE}} +namespace: {{.NAMESPACE}} resources: - ../../base patchesStrategicMerge: diff --git a/template/deployments/kustomize/overlays/production/service.yaml b/template/deployments/kustomize/overlays/production/service.yaml index 7200c7b7..70afda67 100644 --- a/template/deployments/kustomize/overlays/production/service.yaml +++ b/template/deployments/kustomize/overlays/production/service.yaml @@ -1,9 +1,9 @@ apiVersion: v1 kind: Service metadata: - name: {{APPNAME}} - namespace: {{NAMESPACE}} + name: {{.APPNAME}} + namespace: {{.NAMESPACE}} labels: - kubernetes.azure.com/generator: {{GENERATORLABEL}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} spec: type: LoadBalancer diff --git a/template/deployments/manifests/draft.yaml b/template/deployments/manifests/draft.yaml index d1843f41..168794ad 100644 --- a/template/deployments/manifests/draft.yaml +++ b/template/deployments/manifests/draft.yaml @@ -1,29 +1,46 @@ +templateName: "deployment-manifest" +description: "This template is used to create a Kubernetes manifest deployment for an application" +type: "deployment" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: 80 description: "the port exposed in the application" - name: "APPNAME" + type: "string" + kind: "kubernetesResourceName" description: "the name of the application" - name: "SERVICEPORT" + type: "int" + kind: "port" default: referenceVar: "PORT" description: "the port the service uses to make the application accessible from outside the cluster" - name: "NAMESPACE" - default: + type: "string" + kind: "kubernetesNamespace" + default: value: default description: " the namespace to place new resources in" - name: "IMAGENAME" + type: "string" + kind: "containerImageName" default: referenceVar: "APPNAME" description: "the name of the image to use in the deployment" - name: "IMAGETAG" - default: + type: "string" + kind: "containerImageVersion" + default: disablePrompt: true value: "latest" description: "the tag of the image to use in the deployment" - name: "GENERATORLABEL" - default: + type: "string" + kind: "label" + default: disablePrompt: true value: "draft" - description: "the label to identify who generated the resource" \ No newline at end of file + description: "the label to identify who generated the resource" diff --git a/template/deployments/manifests/manifests/deployment.yaml b/template/deployments/manifests/manifests/deployment.yaml index 9b406898..4e07bd64 100644 --- a/template/deployments/manifests/manifests/deployment.yaml +++ b/template/deployments/manifests/manifests/deployment.yaml @@ -1,24 +1,24 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{APPNAME}} + name: {{.APPNAME}} labels: - app: {{APPNAME}} - kubernetes.azure.com/generator: {{GENERATORLABEL}} - namespace: {{NAMESPACE}} + app: {{.APPNAME}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} + namespace: {{.NAMESPACE}} spec: replicas: 1 selector: matchLabels: - app: {{APPNAME}} + app: {{.APPNAME}} template: metadata: labels: - app: {{APPNAME}} + app: {{.APPNAME}} spec: containers: - - name: {{APPNAME}} - image: {{IMAGENAME}}:{{IMAGETAG}} + - name: {{.APPNAME}} + image: {{.IMAGENAME}}:{{.IMAGETAG}} imagePullPolicy: Always ports: - - containerPort: {{PORT}} + - containerPort: {{.PORT}} \ No newline at end of file diff --git a/template/deployments/manifests/manifests/service.yaml b/template/deployments/manifests/manifests/service.yaml index e99c7f41..83481aa4 100644 --- a/template/deployments/manifests/manifests/service.yaml +++ b/template/deployments/manifests/manifests/service.yaml @@ -1,15 +1,15 @@ apiVersion: v1 kind: Service metadata: - name: {{APPNAME}} - namespace: {{NAMESPACE}} + name: {{.APPNAME}} + namespace: {{.NAMESPACE}} labels: - kubernetes.azure.com/generator: {{GENERATORLABEL}} + kubernetes.azure.com/generator: {{.GENERATORLABEL}} spec: type: LoadBalancer selector: - app: {{APPNAME}} + app: {{.APPNAME}} ports: - protocol: TCP - port: {{SERVICEPORT}} - targetPort: {{PORT}} \ No newline at end of file + port: {{.SERVICEPORT}} + targetPort: {{.PORT}} \ No newline at end of file diff --git a/template/dockerfiles/clojure/Dockerfile b/template/dockerfiles/clojure/Dockerfile index 7adf0f73..76957ddc 100644 --- a/template/dockerfiles/clojure/Dockerfile +++ b/template/dockerfiles/clojure/Dockerfile @@ -3,11 +3,11 @@ COPY . /usr/src/app WORKDIR /usr/src/app RUN lein ring uberjar -FROM eclipse-temurin:{{VERSION}} +FROM eclipse-temurin:{{.VERSION}} RUN apk update && apk upgrade && apk add bash -ENV PORT {{PORT}} -EXPOSE {{PORT}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} COPY --from=BUILD /usr/src/app/target/*.jar /opt/ WORKDIR /opt CMD ["/bin/bash", "-c", "find -type f -name '*standalone.jar' | xargs java -jar"] diff --git a/template/dockerfiles/clojure/draft.yaml b/template/dockerfiles/clojure/draft.yaml index 68972ec8..bbe7a1e9 100644 --- a/template/dockerfiles/clojure/draft.yaml +++ b/template/dockerfiles/clojure/draft.yaml @@ -1,13 +1,20 @@ language: clojure displayName: Clojure +templateName: "dockerfile-clojure" +description: "This template is used to create a Dockerfile for a Clojure application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "8-jdk-alpine" description: "the version of openjdk that the application uses" - exampleValues: ["8-jdk-alpine","11-jdk-alpine","17-jdk-alpine","19-jdk-alpine"] \ No newline at end of file + exampleValues: + ["8-jdk-alpine", "11-jdk-alpine", "17-jdk-alpine", "19-jdk-alpine"] diff --git a/template/dockerfiles/csharp/Dockerfile b/template/dockerfiles/csharp/Dockerfile index a762469e..992ad424 100644 --- a/template/dockerfiles/csharp/Dockerfile +++ b/template/dockerfiles/csharp/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:{{VERSION}} AS builder +FROM mcr.microsoft.com/dotnet/sdk:{{.VERSION}} AS builder WORKDIR /app # caches restore result by copying csproj file separately @@ -11,11 +11,11 @@ RUN sed -n 's:.*\(.*\).*:\1:p' *.csproj > __assembl RUN if [ ! -s __assemblyname ]; then filename=$(ls *.csproj); echo ${filename%.*} > __assemblyname; fi # Stage 2 -FROM mcr.microsoft.com/dotnet/aspnet:{{VERSION}} +FROM mcr.microsoft.com/dotnet/aspnet:{{.VERSION}} WORKDIR /app COPY --from=builder /app . -ENV PORT {{PORT}} -EXPOSE {{PORT}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} -ENTRYPOINT dotnet $(cat /app/__assemblyname).dll --urls "http://*:{{PORT}}" +ENTRYPOINT dotnet $(cat /app/__assemblyname).dll --urls "http://*:{{.PORT}}" diff --git a/template/dockerfiles/csharp/draft.yaml b/template/dockerfiles/csharp/draft.yaml index 4b2e667e..4c15c0f2 100644 --- a/template/dockerfiles/csharp/draft.yaml +++ b/template/dockerfiles/csharp/draft.yaml @@ -1,14 +1,19 @@ language: csharp displayName: C# +templateName: "dockerfile-csharp" +description: "This template is used to create a Dockerfile for a C# application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "float" + kind: "containerImageVersion" + default: value: "5.0" description: "the dotnet SDK version" - type: float - exampleValues: ["3.1","4.0","5.0","6.0"] \ No newline at end of file + exampleValues: ["3.1", "4.0", "5.0", "6.0"] diff --git a/template/dockerfiles/erlang/Dockerfile b/template/dockerfiles/erlang/Dockerfile index 30f3e9c1..2245dfe5 100644 --- a/template/dockerfiles/erlang/Dockerfile +++ b/template/dockerfiles/erlang/Dockerfile @@ -1,4 +1,4 @@ -FROM erlang:{{BUILDERVERSION}} as builder +FROM erlang:{{.BUILDERVERSION}} as builder RUN apk add --update tar curl git bash make libc-dev gcc g++ && \ rm -rf /var/cache/apk/* @@ -20,18 +20,18 @@ RUN tar -zxvf /usr/src/app/_build/prod/rel/*/*.tar.gz -C /opt/rel RUN relname=$(ls _build/prod/rel) ; echo $relname > /opt/rel/__relname -FROM alpine:{{VERSION}} +FROM alpine:{{.VERSION}} RUN apk add --no-cache openssl-dev ncurses libstdc++ libgcc WORKDIR /opt/rel ENV RELX_REPLACE_OS_VARS true -ENV HTTP_PORT {{PORT}} +ENV HTTP_PORT {{.PORT}} COPY --from=builder /opt/rel /opt/rel -EXPOSE {{PORT}} {{PORT}} +EXPOSE {{.PORT}} {{.PORT}} RUN ln -s /opt/rel/bin/$(cat /opt/rel/__relname) /opt/rel/bin/start_script ENTRYPOINT ["/opt/rel/bin/start_script"] diff --git a/template/dockerfiles/erlang/draft.yaml b/template/dockerfiles/erlang/draft.yaml index 7a34a264..9d7caf6f 100644 --- a/template/dockerfiles/erlang/draft.yaml +++ b/template/dockerfiles/erlang/draft.yaml @@ -1,19 +1,26 @@ language: erlang displayName: Erlang +templateName: "dockerfile-erlang" +description: "This template is used to create a Dockerfile for an Erlang application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "BUILDERVERSION" - default: - value: "24.2-alpine" + type: "string" + kind: "containerImageVersion" + default: + value: "27.0-alpine" description: "the version of erlang used during the builder stage to generate the executable" - exampleValues: ["24.2-alpine"] + exampleValues: ["27.0-alpine"] - name: "VERSION" - default: - value: "3.15" + type: "string" + kind: "containerImageVersion" + default: + value: "3.17" description: "the version of alpine used by the application" - exampleValues: ["3.15"] - \ No newline at end of file + exampleValues: ["3.17"] diff --git a/template/dockerfiles/go/Dockerfile b/template/dockerfiles/go/Dockerfile index 6975ca6c..368c9086 100644 --- a/template/dockerfiles/go/Dockerfile +++ b/template/dockerfiles/go/Dockerfile @@ -1,6 +1,6 @@ -FROM golang:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM golang:{{.VERSION}} +ENV PORT={{.PORT}} +EXPOSE {{.PORT}} WORKDIR /go/src/app COPY . . diff --git a/template/dockerfiles/go/draft.yaml b/template/dockerfiles/go/draft.yaml index ba978db5..f7ef7c58 100644 --- a/template/dockerfiles/go/draft.yaml +++ b/template/dockerfiles/go/draft.yaml @@ -1,13 +1,19 @@ language: go displayName: Go +templateName: "dockerfile-go" +description: "This template is used to create a Dockerfile for a Go application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: - value: "1.18" + type: "string" + kind: "containerImageVersion" + default: + value: "1.23" description: "the version of go used by the application" - exampleValues: ["1.16", "1.17", "1.18", "1.19"] \ No newline at end of file + exampleValues: ["1.20", "1.21", "1.22", "1.23"] diff --git a/template/dockerfiles/gomodule/Dockerfile b/template/dockerfiles/gomodule/Dockerfile index 2ee0e11f..15ba241b 100644 --- a/template/dockerfiles/gomodule/Dockerfile +++ b/template/dockerfiles/gomodule/Dockerfile @@ -1,6 +1,4 @@ -FROM golang:{{VERSION}} AS builder -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM golang:{{.VERSION}} AS builder WORKDIR /build COPY go.mod go.sum ./ @@ -9,6 +7,10 @@ COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -v -o app-binary FROM gcr.io/distroless/static-debian12 + +ENV PORT={{.PORT}} +EXPOSE {{.PORT}} + WORKDIR /app COPY --from=builder /build/app-binary . CMD ["/app/app-binary"] diff --git a/template/dockerfiles/gomodule/draft.yaml b/template/dockerfiles/gomodule/draft.yaml index bd88a148..55991a10 100644 --- a/template/dockerfiles/gomodule/draft.yaml +++ b/template/dockerfiles/gomodule/draft.yaml @@ -1,13 +1,19 @@ language: gomodule displayName: Go Module +templateName: "dockerfile-gomodule" +description: "This template is used to create a Dockerfile for a Go Module application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: - value: "1.18" + type: "string" + kind: "containerImageVersion" + default: + value: "1.23" description: "the version of go used by the application" - exampleValues: ["1.16", "1.17", "1.18", "1.19"] \ No newline at end of file + exampleValues: ["1.20", "1.21", "1.22", "1.23"] diff --git a/template/dockerfiles/gradle/Dockerfile b/template/dockerfiles/gradle/Dockerfile index 754d1a98..79d9acca 100644 --- a/template/dockerfiles/gradle/Dockerfile +++ b/template/dockerfiles/gradle/Dockerfile @@ -1,11 +1,11 @@ -FROM gradle:{{BUILDERVERSION}} as BUILD +FROM gradle:{{.BUILDERVERSION}} as BUILD COPY --chown=gradle:gradle . /project RUN gradle -i -s -b /project/build.gradle clean build -FROM eclipse-temurin:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM eclipse-temurin:{{.VERSION}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} COPY --from=BUILD /project/build/libs/* /opt/ WORKDIR /opt/ diff --git a/template/dockerfiles/gradle/draft.yaml b/template/dockerfiles/gradle/draft.yaml index 7d62c7a0..182c5117 100644 --- a/template/dockerfiles/gradle/draft.yaml +++ b/template/dockerfiles/gradle/draft.yaml @@ -1,18 +1,26 @@ language: gradle displayName: Gradle +templateName: "dockerfile-gradle" +description: "This template is used to create a Dockerfile for a Gradle application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "BUILDERVERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "jdk21" description: "the version of gradle used during the builder stage to generate the executable" - exampleValues: ["jdk8","jdk11","jdk17","jdk19","jdk21"] + exampleValues: ["jdk8", "jdk11", "jdk17", "jdk19", "jdk21"] - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "21-jre" description: "the java version used by the application" - exampleValues: ["11-jre","17-jre","19-jre","21-jre"] \ No newline at end of file + exampleValues: ["11-jre", "17-jre", "19-jre", "21-jre"] diff --git a/template/dockerfiles/gradlew/Dockerfile b/template/dockerfiles/gradlew/Dockerfile index 4522aa0e..0a09d128 100644 --- a/template/dockerfiles/gradlew/Dockerfile +++ b/template/dockerfiles/gradlew/Dockerfile @@ -1,4 +1,4 @@ -FROM gradle:{{BUILDERVERSION}} as BUILD +FROM gradle:{{.BUILDERVERSION}} as BUILD COPY --chown=gradle:gradle . /project COPY gradlew gradlew @@ -7,9 +7,9 @@ RUN chmod +x gradle/wrapper RUN chmod +x gradlew RUN ./gradlew -i -s -b /project/build.gradle clean build -FROM eclipse-temurin:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM eclipse-temurin:{{.VERSION}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} COPY --from=BUILD /project/build/libs/* /opt/ WORKDIR /opt/ diff --git a/template/dockerfiles/gradlew/draft.yaml b/template/dockerfiles/gradlew/draft.yaml index 7d62c7a0..182c5117 100644 --- a/template/dockerfiles/gradlew/draft.yaml +++ b/template/dockerfiles/gradlew/draft.yaml @@ -1,18 +1,26 @@ language: gradle displayName: Gradle +templateName: "dockerfile-gradle" +description: "This template is used to create a Dockerfile for a Gradle application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "BUILDERVERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "jdk21" description: "the version of gradle used during the builder stage to generate the executable" - exampleValues: ["jdk8","jdk11","jdk17","jdk19","jdk21"] + exampleValues: ["jdk8", "jdk11", "jdk17", "jdk19", "jdk21"] - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "21-jre" description: "the java version used by the application" - exampleValues: ["11-jre","17-jre","19-jre","21-jre"] \ No newline at end of file + exampleValues: ["11-jre", "17-jre", "19-jre", "21-jre"] diff --git a/template/dockerfiles/java/Dockerfile b/template/dockerfiles/java/Dockerfile index d1590ac7..5ab34fdc 100644 --- a/template/dockerfiles/java/Dockerfile +++ b/template/dockerfiles/java/Dockerfile @@ -1,11 +1,11 @@ -FROM maven:{{BUILDERVERSION}} as BUILD +FROM maven:{{.BUILDERVERSION}} as BUILD COPY . /usr/src/app RUN mvn --batch-mode -f /usr/src/app/pom.xml clean package -FROM eclipse-temurin:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM eclipse-temurin:{{.VERSION}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} COPY --from=BUILD /usr/src/app/target /opt/target WORKDIR /opt/target diff --git a/template/dockerfiles/java/draft.yaml b/template/dockerfiles/java/draft.yaml index 33408b75..7cbf81e4 100644 --- a/template/dockerfiles/java/draft.yaml +++ b/template/dockerfiles/java/draft.yaml @@ -1,18 +1,27 @@ language: java displayName: Java +templateName: "dockerfile-java" +description: "This template is used to create a Dockerfile for a Java application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "BUILDERVERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "3" description: "the version of maven used during the builder stage to generate the executable" - exampleValues: ["3-eclipse-temurin-11", "3-eclipse-temurin-17", "3-eclipse-temurin-21", "3 (jdk-21)"] + exampleValues: + ["3-eclipse-temurin-17", "3-eclipse-temurin-21", "3 (jdk-21)"] - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "21-jre" description: "the java version used by the application" - exampleValues: ["11-jre","17-jre","19-jre","21-jre"] \ No newline at end of file + exampleValues: ["11-jre", "17-jre", "19-jre", "21-jre"] diff --git a/template/dockerfiles/javascript/Dockerfile b/template/dockerfiles/javascript/Dockerfile index f4fbc5f5..96c7c168 100644 --- a/template/dockerfiles/javascript/Dockerfile +++ b/template/dockerfiles/javascript/Dockerfile @@ -1,6 +1,6 @@ -FROM node:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM node:{{.VERSION}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} RUN mkdir -p /usr/src/app WORKDIR /usr/src/app diff --git a/template/dockerfiles/javascript/draft.yaml b/template/dockerfiles/javascript/draft.yaml index 9515942e..701bdbc2 100644 --- a/template/dockerfiles/javascript/draft.yaml +++ b/template/dockerfiles/javascript/draft.yaml @@ -1,13 +1,19 @@ language: javascript displayName: JavaScript +templateName: "dockerfile-javascript" +description: "This template is used to create a Dockerfile for a JavaScript application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "14" description: "the version of node used in the application" - exampleValues: ["10.16.3", "12.16.3", "14.15.4"] \ No newline at end of file + exampleValues: ["10.16.3", "12.16.3", "14.15.4"] diff --git a/template/dockerfiles/php/Dockerfile b/template/dockerfiles/php/Dockerfile index 7d61835f..00b7c9fe 100644 --- a/template/dockerfiles/php/Dockerfile +++ b/template/dockerfiles/php/Dockerfile @@ -1,8 +1,8 @@ -FROM composer:{{BUILDERVERSION}} AS build-env +FROM composer:{{.BUILDERVERSION}} AS build-env COPY . /app RUN cd /app && composer install -FROM php:{{VERSION}} +FROM php:{{.VERSION}} ENV PORT 80 EXPOSE 80 COPY --from=build-env /app /var/www/html diff --git a/template/dockerfiles/php/draft.yaml b/template/dockerfiles/php/draft.yaml index ea69173b..1ca077c7 100644 --- a/template/dockerfiles/php/draft.yaml +++ b/template/dockerfiles/php/draft.yaml @@ -1,18 +1,26 @@ language: php displayName: PHP +templateName: "dockerfile-php" +description: "This template is used to create a Dockerfile for a PHP application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "BUILDERVERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "1" description: "the version of composer installed during the build stage to be used by the application" exampleValues: ["1"] - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "7.1-apache" description: "the version of php used by the application" - exampleValues: ["7.1-apache"] \ No newline at end of file + exampleValues: ["7.1-apache"] diff --git a/template/dockerfiles/python/Dockerfile b/template/dockerfiles/python/Dockerfile index 9516b0c4..87e0aa67 100644 --- a/template/dockerfiles/python/Dockerfile +++ b/template/dockerfiles/python/Dockerfile @@ -1,6 +1,6 @@ -FROM python:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM python:{{.VERSION}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} WORKDIR /usr/src/app COPY requirements.txt ./ @@ -9,4 +9,4 @@ RUN pip install --no-cache-dir -r requirements.txt COPY . . ENTRYPOINT ["python"] -CMD ["{{ENTRYPOINT}}"] \ No newline at end of file +CMD ["{{.ENTRYPOINT}}"] \ No newline at end of file diff --git a/template/dockerfiles/python/draft.yaml b/template/dockerfiles/python/draft.yaml index d739aee9..7250eb07 100644 --- a/template/dockerfiles/python/draft.yaml +++ b/template/dockerfiles/python/draft.yaml @@ -1,19 +1,26 @@ language: python displayName: Python +templateName: "dockerfile-python" +description: "This template is used to create a Dockerfile for a Python application" +type: "dockerfile" variables: - name: "PORT" - default: + kind: "port" + type: "int" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "3" description: "the version of python used by the application" exampleValues: ["3.9", "3.8", "3.7", "3.6"] - name: "ENTRYPOINT" - default: + type: "string" + kind: "filePath" + default: value: "app.py" description: "the entrypoint file of the repository" - type: string - exampleValues: ["app.py", "main.py"] \ No newline at end of file + exampleValues: ["app.py", "main.py"] diff --git a/template/dockerfiles/ruby/Dockerfile b/template/dockerfiles/ruby/Dockerfile index 48dafca1..5ffdc260 100644 --- a/template/dockerfiles/ruby/Dockerfile +++ b/template/dockerfiles/ruby/Dockerfile @@ -1,6 +1,6 @@ -FROM ruby:{{VERSION}} -ENV PORT {{PORT}} -EXPOSE {{PORT}} +FROM ruby:{{.VERSION}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} RUN bundle config --global frozen 1 WORKDIR /usr/src/app diff --git a/template/dockerfiles/ruby/draft.yaml b/template/dockerfiles/ruby/draft.yaml index 83cb3678..99d64b99 100644 --- a/template/dockerfiles/ruby/draft.yaml +++ b/template/dockerfiles/ruby/draft.yaml @@ -1,13 +1,19 @@ language: ruby displayName: Ruby +templateName: "dockerfile-ruby" +description: "This template is used to create a Dockerfile for a Ruby application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "3.1.2" description: "the version of ruby used by the application" - exampleValues: ["3.1.2", "2.6", "2.5", "2.4"] \ No newline at end of file + exampleValues: ["3.1.2", "2.6", "2.5", "2.4"] diff --git a/template/dockerfiles/rust/Dockerfile b/template/dockerfiles/rust/Dockerfile index dfb4cb63..86827ea2 100644 --- a/template/dockerfiles/rust/Dockerfile +++ b/template/dockerfiles/rust/Dockerfile @@ -1,10 +1,10 @@ -FROM rust:{{VERSION}} +FROM rust:{{.VERSION}} WORKDIR /usr/src/app COPY . /usr/src/app RUN cargo build -ENV PORT {{PORT}} -EXPOSE {{PORT}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} CMD ["cargo", "run", "-q"] diff --git a/template/dockerfiles/rust/draft.yaml b/template/dockerfiles/rust/draft.yaml index 1588e5f9..284cba73 100644 --- a/template/dockerfiles/rust/draft.yaml +++ b/template/dockerfiles/rust/draft.yaml @@ -1,13 +1,19 @@ language: rust displayName: Rust +templateName: "dockerfile-rust" +description: "This template is used to create a Dockerfile for a Rust application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "1.70.0" description: "the version of rust used by the application" - exampleValues: ["1.70.0","1.65.0", "1.60", "1.54", "1.53"] \ No newline at end of file + exampleValues: ["1.70.0", "1.65.0", "1.60", "1.54", "1.53"] diff --git a/template/dockerfiles/swift/Dockerfile b/template/dockerfiles/swift/Dockerfile index 2bb7f5ae..68594e78 100644 --- a/template/dockerfiles/swift/Dockerfile +++ b/template/dockerfiles/swift/Dockerfile @@ -1,11 +1,11 @@ -FROM swift:{{VERSION}} +FROM swift:{{.VERSION}} WORKDIR /src COPY . /src RUN apt-get update && apt-get install -y sudo openssl libssl-dev libcurl4-openssl-dev RUN swift build -c release -ENV PORT {{PORT}} -EXPOSE {{PORT}} +ENV PORT {{.PORT}} +EXPOSE {{.PORT}} CMD ["swift", "run"] diff --git a/template/dockerfiles/swift/draft.yaml b/template/dockerfiles/swift/draft.yaml index 069c02ff..186d8ffe 100644 --- a/template/dockerfiles/swift/draft.yaml +++ b/template/dockerfiles/swift/draft.yaml @@ -1,13 +1,19 @@ language: swift displayName: Swift +templateName: "dockerfile-swift" +description: "This template is used to create a Dockerfile for a Swift application" +type: "dockerfile" variables: - name: "PORT" - default: + type: "int" + kind: "port" + default: value: "80" description: "the port exposed in the application" - type: int - name: "VERSION" - default: + type: "string" + kind: "containerImageVersion" + default: value: "5.5" description: "the version of swift used by the application" - exampleValues: ["5.2","5.5"] \ No newline at end of file + exampleValues: ["5.2", "5.5"] diff --git a/template/templates.go b/template/templates.go new file mode 100644 index 00000000..9b26c5d7 --- /dev/null +++ b/template/templates.go @@ -0,0 +1,8 @@ +package template + +import "embed" + +var ( + //go:embed all:* + Templates embed.FS +) diff --git a/template/workflows/helm/draft.yaml b/template/workflows/helm/draft.yaml index 12b962ed..b04bf995 100644 --- a/template/workflows/helm/draft.yaml +++ b/template/workflows/helm/draft.yaml @@ -1,44 +1,73 @@ +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" variables: - name: "WORKFLOWNAME" + type: "string" + kind: "workflowName" default: value: "Build and deploy an app to AKS with Helm" description: "the name of the workflow" - name: "BRANCHNAME" + type: "string" + kind: "repositoryBranch" description: "the Github branch to automatically deploy from" - name: "ACRRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the ACR resource group" - name: "AZURECONTAINERREGISTRY" + type: "string" + kind: "azureContainerRegistry" description: "the Azure container registry name" - name: "CONTAINERNAME" + type: "string" + kind: "containerImageName" description: "the container image name" - name: "CLUSTERRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the AKS cluster resource group" - name: "CLUSTERNAME" + type: "string" + kind: "azureManagedCluster" description: "the AKS cluster name" - name: "DOCKERFILE" + type: "string" + kind: "filePath" default: value: "./Dockerfile" description: "the path to the Dockerfile" - name: "BUILDCONTEXTPATH" + type: "string" + kind: "dirPath" default: value: "." description: "the path to the Docker build context" - name: "CHARTPATH" - default: + type: "string" + kind: "dirPath" + default: disablePrompt: true value: "./charts" description: "the path to the Helm chart" - name: "CHARTOVERRIDEPATH" - default: + type: "string" + kind: "dirPath" + default: disablePrompt: true value: "./charts/production.yaml" description: "the path to the Helm chart override file" - name: "CHARTOVERRIDES" - default: + type: "string" + kind: "helmChartOverrides" + default: disablePrompt: true value: "replicas=2" description: "the Helm chart overrides" - name: "NAMESPACE" + type: "string" + kind: "kubernetesNamespace" default: value: "default" - description: "the Kubernetes namespace" \ No newline at end of file + description: "the Kubernetes namespace" diff --git a/template/workflows/kustomize/draft.yaml b/template/workflows/kustomize/draft.yaml index a5cf293d..34bfc63b 100644 --- a/template/workflows/kustomize/draft.yaml +++ b/template/workflows/kustomize/draft.yaml @@ -1,34 +1,59 @@ +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" variables: - name: "WORKFLOWNAME" + type: "string" + kind: "workflowName" default: value: "Build and deploy an app to AKS with Kustomize" description: "the name of the workflow" - name: "BRANCHNAME" + type: "string" + kind: "repositoryBranch" description: "the Github branch to automatically deploy from" - name: "ACRRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the ACR resource group" - name: "AZURECONTAINERREGISTRY" + type: "string" + kind: "azureContainerRegistry" description: "the Azure container registry name" - name: "CONTAINERNAME" + type: "string" + kind: "containerImageName" description: "the container image name" - name: "CLUSTERRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the AKS cluster resource group" - name: "CLUSTERNAME" + type: "string" + kind: "azureManagedCluster" description: "the AKS cluster name" - name: "KUSTOMIZEPATH" - default: + type: "string" + kind: "dirPath" + default: disablePrompt: true value: "./overlays/production" description: "the path to the Kustomize directory" - name: "DOCKERFILE" + type: "string" + kind: "filePath" default: value: "./Dockerfile" description: "the path to the Dockerfile" - name: "BUILDCONTEXTPATH" - default: + type: "string" + kind: "dirPath" + default: value: "." description: "the path to the Docker build context" - name: "NAMESPACE" + type: "string" + kind: "kubernetesNamespace" default: value: "default" description: "the Kubernetes namespace" diff --git a/template/workflows/manifests/draft.yaml b/template/workflows/manifests/draft.yaml index 6aa76160..ebfd9d18 100644 --- a/template/workflows/manifests/draft.yaml +++ b/template/workflows/manifests/draft.yaml @@ -1,34 +1,59 @@ +templateName: "github-workflow-manifest" +description: "This template is used to create a GitHub workflow for building and deploying an app to AKS with kubernetes manifests" +type: "workflow" variables: - name: "WORKFLOWNAME" + type: "string" + kind: "workflowName" default: value: "Build and deploy an app to AKS" description: "the name of the workflow" - name: "BRANCHNAME" + type: "string" + kind: "repositoryBranch" description: "the Github branch to automatically deploy from" - name: "ACRRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the ACR resource group" - name: "AZURECONTAINERREGISTRY" + type: "string" + kind: "azureContainerRegistry" description: "the Azure container registry name" - name: "CONTAINERNAME" + type: "string" + kind: "containerImageName" description: "the container image name" - name: "CLUSTERRESOURCEGROUP" + type: "string" + kind: "azureResourceGroup" description: "the AKS cluster resource group" - name: "CLUSTERNAME" + type: "string" + kind: "azureManagedCluster" description: "the AKS cluster name" - name: "DEPLOYMENTMANIFESTPATH" - default: + type: "string" + kind: "dirPath" + default: disablePrompt: true value: "./manifests" description: "the path to the Kubernetes deployment manifest" - name: "DOCKERFILE" + type: "string" + kind: "filePath" default: value: "./Dockerfile" description: "the path to the Dockerfile" - name: "BUILDCONTEXTPATH" - default: + type: "string" + kind: "dirPath" + default: value: "." description: "the path to the Docker build context" - name: "NAMESPACE" + type: "string" + kind: "kubernetesNamespace" default: value: "default" description: "the Kubernetes namespace" diff --git a/test/info_schema.json b/test/info_schema.json index b93333db..d6b86c38 100644 --- a/test/info_schema.json +++ b/test/info_schema.json @@ -63,7 +63,7 @@ "type": "string", "default": "", "examples": [ - "24.2-alpine" + "27.0-alpine" ], "pattern": "^.*$" } @@ -79,7 +79,7 @@ "type": "string", "default": "", "examples": [ - "3.15" + "3.17" ], "pattern": "^.*$" } diff --git a/test/integration/erlang/helm.yaml b/test/integration/erlang/helm.yaml index e126f803..73fef7ae 100644 --- a/test/integration/erlang/helm.yaml +++ b/test/integration/erlang/helm.yaml @@ -12,8 +12,8 @@ deployVariables: value: "host.minikube.internal:5001/testapp" languageVariables: - name: "VERSION" - value: "3.15" + value: "3.17" - name: "BUILDERVERSION" - value: "24.2-alpine" + value: "27.0-alpine" - name: "PORT" value: "8080" diff --git a/test/integration/erlang/kustomize.yaml b/test/integration/erlang/kustomize.yaml index 5fbc21cb..855f4fc6 100644 --- a/test/integration/erlang/kustomize.yaml +++ b/test/integration/erlang/kustomize.yaml @@ -12,8 +12,8 @@ deployVariables: value: "host.minikube.internal:5001/testapp" languageVariables: - name: "VERSION" - value: "3.15" + value: "3.17" - name: "BUILDERVERSION" - value: "24.2-alpine" + value: "27.0-alpine" - name: "PORT" value: "8080" diff --git a/test/integration/erlang/manifest.yaml b/test/integration/erlang/manifest.yaml index f8748435..628f1421 100644 --- a/test/integration/erlang/manifest.yaml +++ b/test/integration/erlang/manifest.yaml @@ -12,8 +12,8 @@ deployVariables: value: "host.minikube.internal:5001/testapp" languageVariables: - name: "VERSION" - value: "3.15" + value: "3.17" - name: "BUILDERVERSION" - value: "24.2-alpine" + value: "27.0-alpine" - name: "PORT" value: "8080" diff --git a/test/integration_config.json b/test/integration_config.json index 8873eae3..c9385762 100644 --- a/test/integration_config.json +++ b/test/integration_config.json @@ -73,8 +73,8 @@ }, { "language": "erlang", - "version": "3.15", - "builderversion": "24.2-alpine", + "version": "3.17", + "builderversion": "27.0-alpine", "port": "8080", "serviceport": 80, "repo": "bfoley13/ErlangExample"