Repository: Azure/draft
Pull request #207 (2023-04-17 21:34:03)

change default deploytype to avoid defaulting to invalid type
# Description

The default for the deploytype flag is currently set to `.`, which isn't a valid deployment type, and causes a nil pointer error.

In order to catch this in the future, a new smoke test action was added that uses the default for every option.
This smoke test fails with invalid defaults like the one this PR fixes, and we should consider adding one for other commands once we have the ability to extract sane defaults for all of the flags on other commands.

Since the APPNAME variable didn't have a default, I added one to the draft.yaml allowing this smoke test to execute, and providing a basic default for testing.

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# How Has This Been Tested?

Validated with new error return on deployment type lookup
Added new smoke test for create command

# Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream modules


bacongobbler: Upgrade to v0.5.1. This was fixed in the patch release.
bacongobbler: See #182 for diagnosis and solution.

Patch:
diff --git a/cmd/create.go b/cmd/create.go
index 57dcbd5..3e8db48 100644
--- a/cmd/create.go
+++ b/cmd/create.go
@@ -7,11 +7,12 @@ import (
 	"os"
 	"strings"
 
+	"golang.org/x/exp/maps"
+	"gopkg.in/yaml.v3"
+
 	"github.com/manifoldco/promptui"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
-	"golang.org/x/exp/maps"
-	"gopkg.in/yaml.v3"
 
 	"github.com/Azure/draft/pkg/config"
 	"github.com/Azure/draft/pkg/deployments"
@@ -33,6 +34,10 @@ var flagVariablesMap = make(map[string]string)
 const LANGUAGE_VARIABLE = "LANGUAGE"
 const TWO_SPACES = "  "
 
+// Flag defaults
+const emptyDefaultFlagValue = ""
+const currentDirDefaultFlagValue = "."
+
 type createCmd struct {
 	appName    string
 	lang       string
@@ -70,11 +75,11 @@ func newCreateCmd() *cobra.Command {
 
 	f := cmd.Flags()
 
-	f.StringVarP(&cc.createConfigPath, "create-config", "c", "", "specify the path to the configuration file")
-	f.StringVarP(&cc.appName, "app", "a", "", "specify the name of the helm release")
-	f.StringVarP(&cc.lang, "language", "l", "", "specify the language used to create the Kubernetes deployment")
-	f.StringVarP(&cc.dest, "destination", "d", ".", "specify the path to the project directory")
-	f.StringVarP(&cc.deployType, "deploy-type", "", ".", "specify deployement type (eg. helm, kustomize, manifests)")
+	f.StringVarP(&cc.createConfigPath, "create-config", "c", emptyDefaultFlagValue, "specify the path to the configuration file")
+	f.StringVarP(&cc.appName, "app", "a", emptyDefaultFlagValue, "specify the name of the helm release")
+	f.StringVarP(&cc.lang, "language", "l", emptyDefaultFlagValue, "specify the language used to create the Kubernetes deployment")
+	f.StringVarP(&cc.dest, "destination", "d", currentDirDefaultFlagValue, "specify the path to the project directory")
+	f.StringVarP(&cc.deployType, "deploy-type", "", emptyDefaultFlagValue, "specify deployement type (eg. helm, kustomize, manifests)")
 	f.BoolVar(&cc.dockerfileOnly, "dockerfile-only", false, "only create Dockerfile in the project directory")
 	f.BoolVar(&cc.deploymentOnly, "deployment-only", false, "only create deployment files in the project directory")
 	f.BoolVar(&cc.skipFileDetection, "skip-file-detection", false, "skip file detection step")
@@ -287,7 +292,10 @@ func (cc *createCmd) createDeployment() error {
 
 	if cc.createConfig.DeployType != "" {
 		deployType = strings.ToLower(cc.createConfig.DeployType)
-		deployConfig := d.GetConfig(deployType)
+		deployConfig, err := d.GetConfig(deployType)
+		if err != nil {
+			return err
+		}
 		if deployConfig == nil {
 			return errors.New("invalid deployment type")
 		}
@@ -311,7 +319,10 @@ func (cc *createCmd) createDeployment() error {
 			deployType = cc.deployType
 		}
 
-		deployConfig := d.GetConfig(deployType)
+		deployConfig, err := d.GetConfig(deployType)
+		if err != nil {
+			return err
+		}
 		customInputs, err = prompts.RunPromptsFromConfigWithSkips(deployConfig, maps.Keys(flagVariablesMap))
 		if err != nil {
 			return err
diff --git a/cmd/generate-workflow.go b/cmd/generate-workflow.go
index 6e1522d..908f5ac 100644
--- a/cmd/generate-workflow.go
+++ b/cmd/generate-workflow.go
@@ -44,15 +44,15 @@ with draft on AKS. This command assumes the 'setup-gh' command has been run prop
 	}
 
 	f := cmd.Flags()
-	f.StringVarP(&gwCmd.workflowConfig.AksClusterName, "cluster-name", "c", "", "specify the AKS cluster name")
-	f.StringVarP(&gwCmd.workflowConfig.AcrName, "registry-name", "r", "", "specify the Azure container registry name")
-	f.StringVar(&gwCmd.workflowConfig.ContainerName, "container-name", "", "specify the container image name")
-	f.StringVarP(&gwCmd.workflowConfig.ResourceGroupName, "resource-group", "g", "", "specify the Azure resource group of your AKS cluster")
-	f.StringVarP(&gwCmd.dest, "destination", "d", ".", "specify the path to the project directory")
-	f.StringVarP(&gwCmd.workflowConfig.BranchName, "branch", "b", "", "specify the Github branch to automatically deploy from")
-	f.StringVar(&gwCmd.deployType, "deploy-type", "", "specify the type of deployment")
+	f.StringVarP(&gwCmd.workflowConfig.AksClusterName, "cluster-name", "c", emptyDefaultFlagValue, "specify the AKS cluster name")
+	f.StringVarP(&gwCmd.workflowConfig.AcrName, "registry-name", "r", emptyDefaultFlagValue, "specify the Azure container registry name")
+	f.StringVar(&gwCmd.workflowConfig.ContainerName, "container-name", emptyDefaultFlagValue, "specify the container image name")
+	f.StringVarP(&gwCmd.workflowConfig.ResourceGroupName, "resource-group", "g", emptyDefaultFlagValue, "specify the Azure resource group of your AKS cluster")
+	f.StringVarP(&gwCmd.dest, "destination", "d", currentDirDefaultFlagValue, "specify the path to the project directory")
+	f.StringVarP(&gwCmd.workflowConfig.BranchName, "branch", "b", emptyDefaultFlagValue, "specify the Github branch to automatically deploy from")
+	f.StringVar(&gwCmd.deployType, "deploy-type", emptyDefaultFlagValue, "specify the type of deployment")
 	f.StringArrayVarP(&gwCmd.flagVariables, "variable", "", []string{}, "pass additional variables")
-	f.StringVarP(&gwCmd.workflowConfig.BuildContextPath, "build-context-path", "x", "", "specify the docker build context path")
+	f.StringVarP(&gwCmd.workflowConfig.BuildContextPath, "build-context-path", "x", emptyDefaultFlagValue, "specify the docker build context path")
 	gwCmd.templateWriter = &writers.LocalFSWriter{}
 	return cmd
 }
diff --git a/cmd/setup-gh.go b/cmd/setup-gh.go
index cd99cae..3c5efee 100644
--- a/cmd/setup-gh.go
+++ b/cmd/setup-gh.go
@@ -41,10 +41,10 @@ application and service principle, and will configure that application to trust
 	}
 
 	f := cmd.Flags()
-	f.StringVarP(&sc.AppName, "app", "a", "", "specify the Azure Active Directory application name")
-	f.StringVarP(&sc.SubscriptionID, "subscription-id", "s", "", "specify the Azure subscription ID")
-	f.StringVarP(&sc.ResourceGroupName, "resource-group", "r", "", "specify the Azure resource group name")
-	f.StringVarP(&sc.Repo, "gh-repo", "g", "", "specify the github repository link")
+	f.StringVarP(&sc.AppName, "app", "a", emptyDefaultFlagValue, "specify the Azure Active Directory application name")
+	f.StringVarP(&sc.SubscriptionID, "subscription-id", "s", emptyDefaultFlagValue, "specify the Azure subscription ID")
+	f.StringVarP(&sc.ResourceGroupName, "resource-group", "r", emptyDefaultFlagValue, "specify the Azure resource group name")
+	f.StringVarP(&sc.Repo, "gh-repo", "g", emptyDefaultFlagValue, "specify the github repository link")
 	sc.Provider = provider
 	return cmd
 }
diff --git a/pkg/deployments/deployments.go b/pkg/deployments/deployments.go
index 32b3a08..7d13ce7 100644
--- a/pkg/deployments/deployments.go
+++ b/pkg/deployments/deployments.go
@@ -6,10 +6,11 @@ import (
 	"io/fs"
 	"path"
 
-	log "github.com/sirupsen/logrus"
 	"golang.org/x/exp/maps"
 	"gopkg.in/yaml.v3"
 
+	log "github.com/sirupsen/logrus"
+
 	"github.com/Azure/draft/pkg/config"
 	"github.com/Azure/draft/pkg/embedutils"
 	"github.com/Azure/draft/pkg/osutil"
@@ -74,12 +75,12 @@ func (d *Deployments) loadConfig(lang string) (*config.DraftConfig, error) {
 	return &draftConfig, nil
 }
 
-func (d *Deployments) GetConfig(deployType string) *config.DraftConfig {
+func (d *Deployments) GetConfig(deployType string) (*config.DraftConfig, error) {
 	val, ok := d.configs[deployType]
 	if !ok {
-		return nil
+		return nil, fmt.Errorf("deployment type: %s is not currently supported", deployType)
 	}
-	return val
+	return val, nil
 }
 
 func (d *Deployments) PopulateConfigs() {


Test patch:
diff --git a/cmd/create_test.go b/cmd/create_test.go
index 74a14f8..58380f2 100644
--- a/cmd/create_test.go
+++ b/cmd/create_test.go
@@ -207,6 +207,11 @@ func (mcc *createCmd) mockDetectLanguage() (*config.DraftConfig, string, error)
 	return nil, "", ErrNoLanguageDetected
 }
 
+func TestDefaultValues(t *testing.T) {
+	assert.Equal(t, emptyDefaultFlagValue, "")
+	assert.Equal(t, currentDirDefaultFlagValue, ".")
+}
+
 func getAllDeploymentFiles(src string) (error, []string) {
 	deploymentFiles := []string{}
 	err := filepath.Walk(src,