diff --git a/cli/templatecreate.go b/cli/templatecreate.go index e6904d2a065f6..7f2bd4a1bafea 100644 --- a/cli/templatecreate.go +++ b/cli/templatecreate.go @@ -5,8 +5,6 @@ import ( "fmt" "io" "net/http" - "os" - "path/filepath" "strings" "time" "unicode/utf8" @@ -27,7 +25,7 @@ func (r *RootCmd) templateCreate() *clibase.Cmd { provisioner string provisionerTags []string variablesFile string - variables []string + commandLineVariables []string disableEveryone bool requireActiveVersion bool @@ -129,15 +127,21 @@ func (r *RootCmd) templateCreate() *clibase.Cmd { return err } + userVariableValues, err := ParseUserVariableValues( + variablesFile, + commandLineVariables) + if err != nil { + return err + } + job, err := createValidTemplateVersion(inv, createValidTemplateVersionArgs{ - Message: message, - Client: client, - Organization: organization, - Provisioner: codersdk.ProvisionerType(provisioner), - FileID: resp.ID, - ProvisionerTags: tags, - VariablesFile: variablesFile, - Variables: variables, + Message: message, + Client: client, + Organization: organization, + Provisioner: codersdk.ProvisionerType(provisioner), + FileID: resp.ID, + ProvisionerTags: tags, + UserVariableValues: userVariableValues, }) if err != nil { return err @@ -197,12 +201,12 @@ func (r *RootCmd) templateCreate() *clibase.Cmd { { Flag: "variable", Description: "Specify a set of values for Terraform-managed variables.", - Value: clibase.StringArrayOf(&variables), + Value: clibase.StringArrayOf(&commandLineVariables), }, { Flag: "var", Description: "Alias of --variable.", - Value: clibase.StringArrayOf(&variables), + Value: clibase.StringArrayOf(&commandLineVariables), }, { Flag: "provisioner-tag", @@ -267,32 +271,19 @@ type createValidTemplateVersionArgs struct { Provisioner codersdk.ProvisionerType FileID uuid.UUID - VariablesFile string - Variables []string - // Template is only required if updating a template's active version. Template *codersdk.Template // ReuseParameters will attempt to reuse params from the Template field // before prompting the user. Set to false to always prompt for param // values. - ReuseParameters bool - ProvisionerTags map[string]string + ReuseParameters bool + ProvisionerTags map[string]string + UserVariableValues []codersdk.VariableValue } func createValidTemplateVersion(inv *clibase.Invocation, args createValidTemplateVersionArgs) (*codersdk.TemplateVersion, error) { client := args.Client - variableValues, err := loadVariableValuesFromFile(args.VariablesFile) - if err != nil { - return nil, err - } - - variableValuesFromKeyValues, err := loadVariableValuesFromOptions(args.Variables) - if err != nil { - return nil, err - } - variableValues = append(variableValues, variableValuesFromKeyValues...) - req := codersdk.CreateTemplateVersionRequest{ Name: args.Name, Message: args.Message, @@ -300,7 +291,7 @@ func createValidTemplateVersion(inv *clibase.Invocation, args createValidTemplat FileID: args.FileID, Provisioner: args.Provisioner, ProvisionerTags: args.ProvisionerTags, - UserVariableValues: variableValues, + UserVariableValues: args.UserVariableValues, } if args.Template != nil { req.TemplateID = args.Template.ID @@ -364,23 +355,6 @@ func createValidTemplateVersion(inv *clibase.Invocation, args createValidTemplat return &version, nil } -// prettyDirectoryPath returns a prettified path when inside the users -// home directory. Falls back to dir if the users home directory cannot -// discerned. This function calls filepath.Clean on the result. -func prettyDirectoryPath(dir string) string { - dir = filepath.Clean(dir) - homeDir, err := os.UserHomeDir() - if err != nil { - return dir - } - prettyDir := dir - if strings.HasPrefix(prettyDir, homeDir) { - prettyDir = strings.TrimPrefix(prettyDir, homeDir) - prettyDir = "~" + prettyDir - } - return prettyDir -} - func ParseProvisionerTags(rawTags []string) (map[string]string, error) { tags := map[string]string{} for _, rawTag := range rawTags { diff --git a/cli/templatepush.go b/cli/templatepush.go index 0a9af5d941c0e..4c903ef7ca4d9 100644 --- a/cli/templatepush.go +++ b/cli/templatepush.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "io" + "os" "path/filepath" "strings" "time" @@ -155,16 +156,16 @@ func (pf *templateUploadFlags) templateName(args []string) (string, error) { func (r *RootCmd) templatePush() *clibase.Cmd { var ( - versionName string - provisioner string - workdir string - variablesFile string - variables []string - alwaysPrompt bool - provisionerTags []string - uploadFlags templateUploadFlags - activate bool - create bool + versionName string + provisioner string + workdir string + variablesFile string + commandLineVariables []string + alwaysPrompt bool + provisionerTags []string + uploadFlags templateUploadFlags + activate bool + create bool ) client := new(codersdk.Client) cmd := &clibase.Cmd{ @@ -213,15 +214,21 @@ func (r *RootCmd) templatePush() *clibase.Cmd { return err } + userVariableValues, err := ParseUserVariableValues( + variablesFile, + commandLineVariables) + if err != nil { + return err + } + args := createValidTemplateVersionArgs{ - Message: message, - Client: client, - Organization: organization, - Provisioner: codersdk.ProvisionerType(provisioner), - FileID: resp.ID, - ProvisionerTags: tags, - VariablesFile: variablesFile, - Variables: variables, + Message: message, + Client: client, + Organization: organization, + Provisioner: codersdk.ProvisionerType(provisioner), + FileID: resp.ID, + ProvisionerTags: tags, + UserVariableValues: userVariableValues, } if !createTemplate { @@ -291,12 +298,12 @@ func (r *RootCmd) templatePush() *clibase.Cmd { { Flag: "variable", Description: "Specify a set of values for Terraform-managed variables.", - Value: clibase.StringArrayOf(&variables), + Value: clibase.StringArrayOf(&commandLineVariables), }, { Flag: "var", Description: "Alias of --variable.", - Value: clibase.StringArrayOf(&variables), + Value: clibase.StringArrayOf(&commandLineVariables), }, { Flag: "provisioner-tag", @@ -330,3 +337,20 @@ func (r *RootCmd) templatePush() *clibase.Cmd { cmd.Options = append(cmd.Options, uploadFlags.options()...) return cmd } + +// prettyDirectoryPath returns a prettified path when inside the users +// home directory. Falls back to dir if the users home directory cannot +// discerned. This function calls filepath.Clean on the result. +func prettyDirectoryPath(dir string) string { + dir = filepath.Clean(dir) + homeDir, err := os.UserHomeDir() + if err != nil { + return dir + } + prettyDir := dir + if strings.HasPrefix(prettyDir, homeDir) { + prettyDir = strings.TrimPrefix(prettyDir, homeDir) + prettyDir = "~" + prettyDir + } + return prettyDir +} diff --git a/cli/templatevariables.go b/cli/templatevariables.go index 801e65cb8d82f..d284d5cbd8d79 100644 --- a/cli/templatevariables.go +++ b/cli/templatevariables.go @@ -10,7 +10,21 @@ import ( "github.com/coder/coder/v2/codersdk" ) -func loadVariableValuesFromFile(variablesFile string) ([]codersdk.VariableValue, error) { +func ParseUserVariableValues(variablesFile string, commandLineVariables []string) ([]codersdk.VariableValue, error) { + fromFile, err := parseVariableValuesFromFile(variablesFile) + if err != nil { + return nil, err + } + + fromCommandLine, err := parseVariableValuesFromCommandLine(commandLineVariables) + if err != nil { + return nil, err + } + + return combineVariableValues(fromFile, fromCommandLine), nil +} + +func parseVariableValuesFromFile(variablesFile string) ([]codersdk.VariableValue, error) { var values []codersdk.VariableValue if variablesFile == "" { return values, nil @@ -50,7 +64,7 @@ func createVariablesMapFromFile(variablesFile string) (map[string]string, error) return variablesMap, nil } -func loadVariableValuesFromOptions(variables []string) ([]codersdk.VariableValue, error) { +func parseVariableValuesFromCommandLine(variables []string) ([]codersdk.VariableValue, error) { var values []codersdk.VariableValue for _, keyValue := range variables { split := strings.SplitN(keyValue, "=", 2) @@ -65,3 +79,20 @@ func loadVariableValuesFromOptions(variables []string) ([]codersdk.VariableValue } return values, nil } + +func combineVariableValues(valuesSets ...[]codersdk.VariableValue) []codersdk.VariableValue { + combinedValues := make(map[string]string) + + for _, values := range valuesSets { + for _, v := range values { + combinedValues[v.Name] = v.Value + } + } + + var result []codersdk.VariableValue + for name, value := range combinedValues { + result = append(result, codersdk.VariableValue{Name: name, Value: value}) + } + + return result +}