Skip to content

Commit 96f500a

Browse files
Mauricio FerrariVidya2606
andauthored
Workflow Template Enhancements (#324)
Co-authored-by: Vidya Reddy <[email protected]>
1 parent 5cf07bd commit 96f500a

File tree

18 files changed

+499
-136
lines changed

18 files changed

+499
-136
lines changed

.github/workflows/integration-linux.yml

Lines changed: 36 additions & 36 deletions
Large diffs are not rendered by default.

cmd/create.go

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func (cc *createCmd) generateDockerfile(langConfig *config.DraftConfig, lowerLan
292292
return err
293293
}
294294
} else {
295-
inputs, err = validateConfigInputsToPrompts(langConfig.Variables, cc.createConfig.LanguageVariables)
295+
inputs, err = validateConfigInputsToPrompts(langConfig, cc.createConfig.LanguageVariables)
296296
if err != nil {
297297
return err
298298
}
@@ -330,7 +330,7 @@ func (cc *createCmd) createDeployment() error {
330330
if deployConfig == nil {
331331
return errors.New("invalid deployment type")
332332
}
333-
customInputs, err = validateConfigInputsToPrompts(deployConfig.Variables, cc.createConfig.DeployVariables)
333+
customInputs, err = validateConfigInputsToPrompts(deployConfig, cc.createConfig.DeployVariables)
334334
if err != nil {
335335
return err
336336
}
@@ -464,31 +464,19 @@ func init() {
464464
rootCmd.AddCommand(newCreateCmd())
465465
}
466466

467-
func validateConfigInputsToPrompts(required []config.BuilderVar, provided []UserInputs) (map[string]string, error) {
467+
func validateConfigInputsToPrompts(draftConfig *config.DraftConfig, provided []UserInputs) (map[string]string, error) {
468468
customInputs := make(map[string]string)
469469

470470
// set inputs to provided values
471471
for _, variable := range provided {
472472
customInputs[variable.Name] = variable.Value
473473
}
474474

475-
// fill in missing vars using variable default references
476-
for _, variable := range required {
477-
if customInputs[variable.Name] == "" && variable.Default.ReferenceVar != "" {
478-
log.Debugf("variable %s is empty, using default referenceVar value from %s", variable.Name, variable.Default.ReferenceVar)
479-
customInputs[variable.Name] = customInputs[variable.Default.ReferenceVar]
480-
}
481-
}
482-
483-
// fill in missing vars using variable default values
484-
for _, variable := range required {
485-
if customInputs[variable.Name] == "" && variable.Default.Value != "" {
486-
log.Debugf("variable %s is empty, using default value %s", variable.Name, variable.Default.Value)
487-
customInputs[variable.Name] = variable.Default.Value
488-
}
475+
if err := draftConfig.ApplyDefaultVariables(customInputs); err != nil {
476+
return nil, fmt.Errorf("validate config inputs to prompts: %w", err)
489477
}
490478

491-
for _, variable := range required {
479+
for _, variable := range draftConfig.Variables {
492480
value, ok := customInputs[variable.Name]
493481
if !ok {
494482
return nil, fmt.Errorf("config missing required variable: %s with description: %s", variable.Name, variable.Description)

cmd/create_test.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,40 +142,44 @@ func TestInitConfig(t *testing.T) {
142142
}
143143

144144
func TestValidateConfigInputsToPromptsPass(t *testing.T) {
145-
required := []config.BuilderVar{
146-
{
147-
Name: "REQUIRED_PROVIDED",
148-
},
149-
{
150-
Name: "REQUIRED_DEFAULTED",
151-
Default: config.BuilderVarDefault{
152-
Value: "DEFAULT_VALUE",
145+
required := config.DraftConfig{
146+
Variables: []config.BuilderVar{
147+
{
148+
Name: "REQUIRED_PROVIDED",
149+
},
150+
{
151+
Name: "REQUIRED_DEFAULTED",
152+
Default: config.BuilderVarDefault{
153+
Value: "DEFAULT_VALUE",
154+
},
153155
},
154156
},
155157
}
156158
provided := []UserInputs{
157159
{Name: "REQUIRED_PROVIDED", Value: "PROVIDED_VALUE"},
158160
}
159161

160-
vars, err := validateConfigInputsToPrompts(required, provided)
162+
vars, err := validateConfigInputsToPrompts(&required, provided)
161163
assert.True(t, err == nil)
162164
assert.Equal(t, vars["REQUIRED_DEFAULTED"], "DEFAULT_VALUE")
163165
}
164166

165167
func TestValidateConfigInputsToPromptsMissing(t *testing.T) {
166-
required := []config.BuilderVar{
167-
{
168-
Name: "REQUIRED_PROVIDED",
169-
},
170-
{
171-
Name: "REQUIRED_MISSING",
168+
required := config.DraftConfig{
169+
Variables: []config.BuilderVar{
170+
{
171+
Name: "REQUIRED_PROVIDED",
172+
},
173+
{
174+
Name: "REQUIRED_MISSING",
175+
},
172176
},
173177
}
174178
provided := []UserInputs{
175179
{Name: "REQUIRED_PROVIDED"},
176180
}
177181

178-
_, err := validateConfigInputsToPrompts(required, provided)
182+
_, err := validateConfigInputsToPrompts(&required, provided)
179183
assert.NotNil(t, err)
180184
}
181185

cmd/generate-workflow.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,20 @@ with draft on AKS. This command assumes the 'setup-gh' command has been run prop
5252
}
5353

5454
f := cmd.Flags()
55-
f.StringVarP(&gwCmd.workflowConfig.AksClusterName, "cluster-name", "c", emptyDefaultFlagValue, "specify the AKS cluster name")
56-
f.StringVarP(&gwCmd.workflowConfig.AcrName, "registry-name", "r", emptyDefaultFlagValue, "specify the Azure container registry name")
57-
f.StringVar(&gwCmd.workflowConfig.ContainerName, "container-name", emptyDefaultFlagValue, "specify the container image name")
58-
f.StringVarP(&gwCmd.workflowConfig.ResourceGroupName, "resource-group", "g", emptyDefaultFlagValue, "specify the Azure resource group of your AKS cluster")
5955
f.StringVarP(&gwCmd.dest, "destination", "d", currentDirDefaultFlagValue, "specify the path to the project directory")
60-
f.StringVarP(&gwCmd.workflowConfig.BranchName, "branch", "b", emptyDefaultFlagValue, "specify the Github branch to automatically deploy from")
6156
f.StringVar(&gwCmd.deployType, "deploy-type", emptyDefaultFlagValue, "specify the type of deployment")
62-
f.StringArrayVarP(&gwCmd.flagVariables, "variable", "", []string{}, "pass additional variables")
57+
f.StringVarP(&gwCmd.workflowConfig.WorkflowName, "workflow", "w", emptyDefaultFlagValue, "specify the Github workflow name")
58+
f.StringVarP(&gwCmd.workflowConfig.BranchName, "branch", "b", emptyDefaultFlagValue, "specify the Github branch to automatically deploy from")
59+
f.StringVar(&gwCmd.workflowConfig.AcrResourceGroup, "acr-resource-group", emptyDefaultFlagValue, "specify the Azure container registry resource group")
60+
f.StringVarP(&gwCmd.workflowConfig.AcrName, "registry-name", "r", emptyDefaultFlagValue, "specify the Azure container registry name")
61+
f.StringVar(&gwCmd.workflowConfig.ContainerName, "container-name", emptyDefaultFlagValue, "specify the container image name")
62+
f.StringVarP(&gwCmd.workflowConfig.ClusterResourceGroup, "cluster-resource-group", "g", emptyDefaultFlagValue, "specify the Azure resource group of your AKS cluster")
63+
f.StringVarP(&gwCmd.workflowConfig.ClusterName, "cluster-name", "c", emptyDefaultFlagValue, "specify the AKS cluster name")
64+
f.StringVar(&gwCmd.workflowConfig.Dockerfile, "dockerfile", emptyDefaultFlagValue, "specify the path to the Dockerfile")
6365
f.StringVarP(&gwCmd.workflowConfig.BuildContextPath, "build-context-path", "x", emptyDefaultFlagValue, "specify the docker build context path")
66+
f.StringVarP(&gwCmd.workflowConfig.Namespace, "namespace", "n", emptyDefaultFlagValue, "specify the Kubernetes namespace")
67+
f.StringVar(&gwCmd.workflowConfig.PrivateCluster, "private-cluster", emptyDefaultFlagValue, "specify if the AKS cluster is private")
68+
f.StringArrayVarP(&gwCmd.flagVariables, "variable", "", []string{}, "pass additional variables")
6469
gwCmd.templateWriter = &writers.LocalFSWriter{}
6570
return cmd
6671
}
@@ -109,4 +114,4 @@ func (gwc *generateWorkflowCmd) generateWorkflows(dest string, deployType string
109114
maps.Copy(customInputs, flagValuesMap)
110115

111116
return workflow.CreateWorkflowFiles(deployType, customInputs, templateWriter)
112-
}
117+
}

pkg/config/draftconfig.go

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package config
22

33
import (
44
"errors"
5+
"fmt"
56

67
log "github.com/sirupsen/logrus"
78
)
@@ -26,6 +27,7 @@ type BuilderVar struct {
2627
Description string `yaml:"description"`
2728
ExampleValues []string `yaml:"exampleValues"`
2829
Type string `yaml:"type"`
30+
Value string `yaml:"value"`
2931
}
3032

3133
type BuilderVarDefault struct {
@@ -67,21 +69,50 @@ func (d *DraftConfig) GetNameOverride(path string) string {
6769
}
6870

6971
// ApplyDefaultVariables will apply the defaults to variables that are not already set
70-
func (d *DraftConfig) ApplyDefaultVariables(customConfig map[string]string) error {
72+
func (d *DraftConfig) ApplyDefaultVariables(customInputs map[string]string) error {
73+
varIdxMap := VariableIdxMap(d.Variables)
74+
7175
for _, variable := range d.Variables {
7276
// handle where variable is not set or is set to an empty string from cli handling
73-
if val, ok := customConfig[variable.Name]; !ok || val == "" {
74-
if variable.Default.Value == "" {
75-
return errors.New("variable " + variable.Name + " has no default value")
77+
if customInputs[variable.Name] == "" {
78+
if variable.Default.ReferenceVar != "" {
79+
defaultVal, err := recurseReferenceVars(d.Variables, d.Variables[varIdxMap[variable.Default.ReferenceVar]], customInputs, varIdxMap, d.Variables[varIdxMap[variable.Default.ReferenceVar]], true)
80+
if err != nil {
81+
return fmt.Errorf("apply default variables: %w", err)
82+
}
83+
log.Infof("Variable %s defaulting to value %s", variable.Name, customInputs[variable.Name])
84+
customInputs[variable.Name] = defaultVal
85+
}
86+
87+
if customInputs[variable.Name] == "" {
88+
if variable.Default.Value != "" {
89+
log.Infof("Variable %s defaulting to value %s", variable.Name, variable.Default.Value)
90+
customInputs[variable.Name] = variable.Default.Value
91+
} else {
92+
return fmt.Errorf("variable %s has no default value", variable.Name)
93+
}
7694
}
77-
log.Infof("Variable %s defaulting to value %s", variable.Name, variable.Default.Value)
78-
customConfig[variable.Name] = variable.Default.Value
7995
}
8096
}
8197

8298
return nil
8399
}
84100

101+
// recurseReferenceVars recursively checks each variable's ReferenceVar if it doesn't have a custom input. If there's no more ReferenceVars, it will return the default value of the last ReferenceVar.
102+
func recurseReferenceVars(variables []BuilderVar, variable BuilderVar, customInputs map[string]string, varIdxMap map[string]int, variableCheck BuilderVar, isFirst bool) (string, error) {
103+
if !isFirst && variable.Name == variableCheck.Name {
104+
return "", errors.New("cyclical reference detected")
105+
}
106+
107+
if customInputs[variable.Name] != "" {
108+
return customInputs[variable.Name], nil
109+
} else if variable.Default.ReferenceVar != "" {
110+
return recurseReferenceVars(variables, variables[varIdxMap[variable.Default.ReferenceVar]], customInputs, varIdxMap, variableCheck, false)
111+
}
112+
113+
return variable.Default.Value, nil
114+
}
115+
85116
func VariableIdxMap(variables []BuilderVar) map[string]int {
86117
varIdxMap := make(map[string]int)
87118

@@ -92,6 +123,31 @@ func VariableIdxMap(variables []BuilderVar) map[string]int {
92123
return varIdxMap
93124
}
94125

126+
func (d *DraftConfig) VariableMap() (map[string]string, error) {
127+
envArgs := make(map[string]string)
128+
129+
for _, variable := range d.Variables {
130+
envArgs[variable.Name] = variable.Value
131+
}
132+
133+
err := d.ApplyDefaultVariables(envArgs)
134+
if err != nil {
135+
return nil, fmt.Errorf("creating variable map: %w", err)
136+
}
137+
138+
return envArgs, nil
139+
}
140+
141+
func (d *DraftConfig) VariableIdxMap() map[string]int {
142+
varIdxMap := make(map[string]int)
143+
144+
for i, variable := range d.Variables {
145+
varIdxMap[variable.Name] = i
146+
}
147+
148+
return varIdxMap
149+
}
150+
95151
// TemplateVariableRecorder is an interface for recording variables that are used read using draft configs
96152
type TemplateVariableRecorder interface {
97153
Record(key, value string)

0 commit comments

Comments
 (0)