Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few updates to draft #277

Merged
merged 8 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion cmd/generate-workflow.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package cmd

import (
"fmt"
"strings"

"github.com/manifoldco/promptui"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/exp/maps"

"github.com/Azure/draft/pkg/prompts"
"github.com/Azure/draft/pkg/templatewriter"
"github.com/Azure/draft/pkg/templatewriter/writers"
"github.com/Azure/draft/pkg/workflows"
"github.com/Azure/draft/template"
)

type generateWorkflowCmd struct {
Expand Down Expand Up @@ -34,7 +41,7 @@ with draft on AKS. This command assumes the 'setup-gh' command has been run prop
flagValuesMap = gwCmd.workflowConfig.SetFlagValuesToMap()
}
log.Info("--> Generating Github workflow")
if err := workflows.CreateWorkflows(gwCmd.dest, gwCmd.deployType, gwCmd.flagVariables, gwCmd.templateWriter, flagValuesMap); err != nil {
if err := gwCmd.generateWorkflows(gwCmd.dest, gwCmd.deployType, gwCmd.flagVariables, gwCmd.templateWriter, flagValuesMap); err != nil {
return err
}

Expand All @@ -61,3 +68,45 @@ with draft on AKS. This command assumes the 'setup-gh' command has been run prop
func init() {
rootCmd.AddCommand(newGenerateWorkflowCmd())
}

func (gwc *generateWorkflowCmd) generateWorkflows(dest string, deployType string, flagVariables []string, templateWriter templatewriter.TemplateWriter, flagValuesMap map[string]string) error {
if flagValuesMap == nil {
return fmt.Errorf("flagValuesMap is nil")
}
var err error
for _, flagVar := range flagVariables {
flagVarName, flagVarValue, ok := strings.Cut(flagVar, "=")
if !ok {
return fmt.Errorf("invalid variable format: %s", flagVar)
}
flagValuesMap[flagVarName] = flagVarValue
log.Debugf("flag variable %s=%s", flagVarName, flagVarValue)
}

if deployType == "" {
selection := &promptui.Select{
Label: "Select k8s Deployment Type",
Items: []string{"helm", "kustomize", "manifests"},
}

_, deployType, err = selection.Run()
if err != nil {
return err
}
}

workflow := workflows.CreateWorkflowsFromEmbedFS(template.Workflows, dest)
workflowConfig, err := workflow.GetConfig(deployType)
if err != nil {
return fmt.Errorf("get config: %w", err)
}

customInputs, err := prompts.RunPromptsFromConfigWithSkips(workflowConfig, maps.Keys(flagValuesMap))
if err != nil {
return err
}

maps.Copy(customInputs, flagValuesMap)

return workflow.CreateWorkflowFiles(deployType, customInputs, templateWriter)
}
4 changes: 2 additions & 2 deletions example/dockerfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ func TestWriteDockerfile(t *testing.T) {
expectError: false,
},
{
name: "Test Invalid Go Dockerfile Generation",
name: "Test Valid Go Dockerfile Generation with deafult",
inputVariables: map[string]string{
"PORT": "8080",
},
generationLanguage: "go",
expectError: true,
expectError: false,
},
{
name: "Test Invalid GenerationLanguage",
Expand Down
2 changes: 2 additions & 0 deletions pkg/addons/addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func GenerateAddon(addons embed.FS, provider, addon, dest string, userInputs map
return err
}

addOnConfig.ApplyDefaultVariables(userInputs)

if err = osutil.CopyDir(addons, selectedAddonPath, addonDestPath, &addOnConfig.DraftConfig, userInputs, templateWriter); err != nil {
return err
}
Expand Down
19 changes: 15 additions & 4 deletions pkg/config/draftconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ type BuilderVar struct {
Description string `yaml:"description"`
VarType string `yaml:"type"`
ExampleValues []string `yaml:"exampleValues"`
IsPromptDisabled bool `yaml:"disablePrompt"`
davidgamero marked this conversation as resolved.
Show resolved Hide resolved
}

type BuilderVarDefault struct {
Name string `yaml:"name"`
Value string `yaml:"value"`
ReferenceVar string `yaml:"referenceVar"`
Name string `yaml:"name"`
Value string `yaml:"value"`
ReferenceVar string `yaml:"referenceVar"`
IsPromptDisabled bool `yaml:"disablePrompt"`
}

func (d *DraftConfig) GetVariableExampleValues() map[string][]string {
Expand Down Expand Up @@ -64,6 +64,17 @@ func (d *DraftConfig) GetNameOverride(path string) string {
return prefix
}

// ApplyDefaultVariables will apply the defaults to variables that are not already set
func (d *DraftConfig) ApplyDefaultVariables(customConfig map[string]string) {
for _, variable := range d.VariableDefaults {
// handle where variable is not set or is set to an empty string from cli handling
if defaultVal, ok := customConfig[variable.Name]; !ok || defaultVal == "" {
log.Infof("Variable %s defaulting to value %s", variable.Name, variable.Value)
customConfig[variable.Name] = variable.Value
}
}
}

// TemplateVariableRecorder is an interface for recording variables that are used read using draft configs
type TemplateVariableRecorder interface {
Record(key, value string)
Expand Down
2 changes: 2 additions & 0 deletions pkg/deployments/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func (d *Deployments) CopyDeploymentFiles(deployType string, customInputs map[st
deployConfig, ok := d.configs[deployType]
if !ok {
deployConfig = nil
} else {
deployConfig.ApplyDefaultVariables(customInputs)
}

if err := osutil.CopyDir(d.deploymentTemplates, srcDir, d.dest, deployConfig, customInputs, templateWriter); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/languages/languages.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ func (l *Languages) CreateDockerfileForLanguage(lang string, customInputs map[st
draftConfig, ok := l.configs[lang]
if !ok {
draftConfig = nil
} else {
draftConfig.ApplyDefaultVariables(customInputs)
}

if err := osutil.CopyDir(l.dockerfileTemplates, srcDir, l.dest, draftConfig, customInputs, templateWriter); err != nil {
Expand Down
11 changes: 10 additions & 1 deletion pkg/prompts/prompts.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func RunPromptsFromConfigWithSkipsIO(config *config.DraftConfig, varsToSkip []st
log.Debugf("Skipping prompt for %s", promptVariableName)
continue
}
if customPrompt.IsPromptDisabled {
if GetIsPromptDisabled(customPrompt.Name, config.VariableDefaults) {
log.Debugf("Skipping prompt for %s as it has IsPromptDisabled=true", promptVariableName)
noPromptDefaultValue := GetVariableDefaultValue(promptVariableName, config.VariableDefaults, inputs)
if noPromptDefaultValue == "" {
Expand Down Expand Up @@ -90,6 +90,15 @@ func GetVariableDefaultValue(variableName string, variableDefaults []config.Buil
return defaultValue
}

func GetIsPromptDisabled(variableName string, variableDefaults []config.BuilderVarDefault) bool {
for _, variableDefault := range variableDefaults {
if variableDefault.Name == variableName {
return variableDefault.IsPromptDisabled
}
}
return false
}

func RunBoolPrompt(customPrompt config.BuilderVar, Stdin io.ReadCloser, Stdout io.WriteCloser) (string, error) {
newSelect := &promptui.Select{
Label: "Please select " + customPrompt.Description,
Expand Down
6 changes: 3 additions & 3 deletions pkg/prompts/prompts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ func TestRunPromptsFromConfigWithSkipsIO(t *testing.T) {
{
Name: "var1",
Description: "var1 description",
IsPromptDisabled: true,
},
},
VariableDefaults: []config.BuilderVarDefault{
{
Name: "var1",
Value: "defaultValue",
IsPromptDisabled: true,
},
},
},
Expand All @@ -176,14 +176,12 @@ func TestRunPromptsFromConfigWithSkipsIO(t *testing.T) {
{
Name: "var1-no-prompt",
Description: "var1 has IsPromptDisabled and should skip prompt and use default value",
IsPromptDisabled: true,
}, {
Name: "var2-default",
Description: "var2 has a default value and will receive an empty value, so it should use the default value",
}, {
Name: "var3-no-prompt",
Description: "var3 has IsPromptDisabled and should skip prompt and use default value",
IsPromptDisabled: true,
}, {
Name: "var4",
Description: "var4 has a default value, but has a value entered, so it should use the entered value",
Expand All @@ -193,12 +191,14 @@ func TestRunPromptsFromConfigWithSkipsIO(t *testing.T) {
{
Name: "var1-no-prompt",
Value: "defaultValueNoPrompt1",
IsPromptDisabled: true,
}, {
Name: "var2-default",
Value: "defaultValue2",
}, {
Name: "var3-no-prompt",
Value: "defaultValueNoPrompt3",
IsPromptDisabled: true,
}, {
Name: "var4",
Value: "defaultValue4",
Expand Down
67 changes: 16 additions & 51 deletions pkg/workflows/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,18 @@ import (
"io/ioutil"
"os"
"path"
"strings"

"golang.org/x/exp/maps"
"gopkg.in/yaml.v3"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/cli-runtime/pkg/printers"
"k8s.io/client-go/kubernetes/scheme"

"github.com/manifoldco/promptui"
log "github.com/sirupsen/logrus"

"github.com/Azure/draft/pkg/config"
"github.com/Azure/draft/pkg/embedutils"
"github.com/Azure/draft/pkg/osutil"
"github.com/Azure/draft/pkg/prompts"
"github.com/Azure/draft/pkg/templatewriter"
"github.com/Azure/draft/template"
)

const (
Expand All @@ -39,50 +34,6 @@ type Workflows struct {
workflowTemplates fs.FS
}

func CreateWorkflows(dest string, deployType string, flagVariables []string, templateWriter templatewriter.TemplateWriter, flagValuesMap map[string]string) error {
if flagValuesMap == nil {
return fmt.Errorf("flagValuesMap is nil")
}
var err error
for _, flagVar := range flagVariables {
flagVarName, flagVarValue, ok := strings.Cut(flagVar, "=")
if !ok {
return fmt.Errorf("invalid variable format: %s", flagVar)
}
flagValuesMap[flagVarName] = flagVarValue
log.Debugf("flag variable %s=%s", flagVarName, flagVarValue)
}

if deployType == "" {
selection := &promptui.Select{
Label: "Select k8s Deployment Type",
Items: []string{"helm", "kustomize", "manifests"},
}

_, deployType, err = selection.Run()
if err != nil {
return err
}
}

workflow := createWorkflowsFromEmbedFS(template.Workflows, dest)
workflowConfig, ok := workflow.configs[deployType]
if !ok {
return errors.New("invalid deployment type")
}
customInputs, err := prompts.RunPromptsFromConfigWithSkips(workflowConfig, maps.Keys(flagValuesMap))
if err != nil {
return err
}

maps.Copy(customInputs, flagValuesMap)

if err = updateProductionDeployments(deployType, dest, customInputs, templateWriter); err != nil {
return err
}
return workflow.createWorkflowFiles(deployType, customInputs, templateWriter)
}

func updateProductionDeployments(deployType, dest string, flagValuesMap map[string]string, templateWriter templatewriter.TemplateWriter) error {
productionImage := fmt.Sprintf("%s.azurecr.io/%s", flagValuesMap["AZURECONTAINERREGISTRY"], flagValuesMap["CONTAINERNAME"])
switch deployType {
Expand Down Expand Up @@ -176,7 +127,15 @@ func (w *Workflows) loadConfig(deployType string) (*config.DraftConfig, error) {
return &draftConfig, nil
}

func createWorkflowsFromEmbedFS(workflowTemplates embed.FS, dest string) *Workflows {
func (w *Workflows) GetConfig(deployType string) (*config.DraftConfig, error) {
val, ok := w.configs[deployType]
if !ok {
return nil, fmt.Errorf("deploy type %s unsupported", deployType)
}
return val, nil
}

func CreateWorkflowsFromEmbedFS(workflowTemplates embed.FS, dest string) *Workflows {
deployMap, err := embedutils.EmbedFStoMap(workflowTemplates, parentDirName)
if err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -204,7 +163,7 @@ func (w *Workflows) populateConfigs() {
}
}

func (w *Workflows) createWorkflowFiles(deployType string, customInputs map[string]string, templateWriter templatewriter.TemplateWriter) error {
func (w *Workflows) CreateWorkflowFiles(deployType string, customInputs map[string]string, templateWriter templatewriter.TemplateWriter) error {
val, ok := w.workflows[deployType]
if !ok {
return fmt.Errorf("deployment type: %s is not currently supported", deployType)
Expand All @@ -214,6 +173,12 @@ func (w *Workflows) createWorkflowFiles(deployType string, customInputs map[stri
workflowConfig, ok := w.configs[deployType]
if !ok {
workflowConfig = nil
} else {
workflowConfig.ApplyDefaultVariables(customInputs)
}

if err := updateProductionDeployments(deployType, w.dest, customInputs, templateWriter); err != nil {
return fmt.Errorf("update production deployments: %w", err)
}

if err := osutil.CopyDir(w.workflowTemplates, srcDir, w.dest, workflowConfig, customInputs, templateWriter); err != nil {
Expand Down
14 changes: 7 additions & 7 deletions pkg/workflows/workflows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
func TestCreateWorkflows(t *testing.T) {
dest := "."
deployType := "helm"
flagVariables := []string{}
templatewriter := &writers.LocalFSWriter{}
flagValuesMap := map[string]string{"AZURECONTAINERREGISTRY": "testAcr", "CONTAINERNAME": "testContainer", "RESOURCEGROUP": "testRG", "CLUSTERNAME": "testCluster", "BRANCHNAME": "testBranch", "BUILDCONTEXTPATH": "."}
flagValuesMapNoRoot := map[string]string{"AZURECONTAINERREGISTRY": "testAcr", "CONTAINERNAME": "testContainer", "RESOURCEGROUP": "testRG", "CLUSTERNAME": "testCluster", "BRANCHNAME": "testBranch", "BUILDCONTEXTPATH": "test"}
Expand Down Expand Up @@ -108,11 +107,12 @@ func TestCreateWorkflows(t *testing.T) {
err := createTempDeploymentFile("charts", "charts/production.yaml", "../../test/templates/helm/charts/production.yaml")
assert.Nil(t, err)

err = CreateWorkflows(dest, deployType, flagVariables, templatewriter, flagValuesMap)
workflows := CreateWorkflowsFromEmbedFS(template.Workflows, dest)
err = workflows.CreateWorkflowFiles(deployType, flagValuesMap, templatewriter)
if err != nil {
t.Errorf("Default Build Context CreateWorkflows() error = %v, wantErr %v", err, tt.shouldError)
}
err = CreateWorkflows(dest, deployType, flagVariables, templatewriter, flagValuesMapNoRoot)
err = workflows.CreateWorkflowFiles(deployType, flagValuesMapNoRoot, templatewriter)
if err != nil {
t.Errorf("Custom Build Context CreateWorkflows() error = %v, wantErr %v", err, tt.shouldError)
}
Expand Down Expand Up @@ -248,18 +248,18 @@ func TestCreateWorkflowFiles(t *testing.T) {

mockWF.populateConfigs()

err = mockWF.createWorkflowFiles("fakeDeployType", customInputs, templatewriter)
err = mockWF.CreateWorkflowFiles("fakeDeployType", customInputs, templatewriter)
assert.NotNil(t, err)

err = mockWF.createWorkflowFiles("helm", customInputs, templatewriter)
err = mockWF.CreateWorkflowFiles("helm", customInputs, templatewriter)
assert.Nil(t, err)
os.RemoveAll(".github")

err = mockWF.createWorkflowFiles("helm", customInputsNoRoot, templatewriter)
err = mockWF.CreateWorkflowFiles("helm", customInputsNoRoot, templatewriter)
assert.Nil(t, err)
os.RemoveAll(".github")

err = mockWF.createWorkflowFiles("helm", badInputs, templatewriter)
err = mockWF.CreateWorkflowFiles("helm", badInputs, templatewriter)
assert.NotNil(t, err)
os.RemoveAll(".github")
}
Expand Down
6 changes: 6 additions & 0 deletions template/addons/azure/webapp_routing/draft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ variables:
type: "bool"
- name: "ingress-host"
description: "specify the host of the ingress resource"
- name: "GENERATORLABEL"
description: "the label to identify who generated the resource"
variableDefaults:
- name: "GENERATORLABEL"
value: "draft"
disablePrompt: true
references:
service:
- name: "service-name"
Expand Down
Loading
Loading