@@ -24,16 +24,18 @@ import (
2424 "hpc-toolkit/pkg/modulewriter"
2525 "log"
2626 "os"
27+ "strings"
2728
2829 "github.com/spf13/cobra"
30+ "github.com/zclconf/go-cty/cty"
31+ "gopkg.in/yaml.v3"
2932)
3033
3134const msgCLIVars = "Comma-separated list of name=value variables to override YAML configuration. Can be used multiple times."
3235const msgCLIBackendConfig = "Comma-separated list of name=value variables to set Terraform backend configuration. Can be used multiple times."
3336
3437func init () {
35- createCmd .Flags ().StringVarP (& bpFilename , "config" , "c" , "" ,
36- "HPC Environment Blueprint file to be used to create an HPC deployment dir." )
38+ createCmd .Flags ().StringVarP (& bpFilenameDeprecated , "config" , "c" , "" , "" )
3739 cobra .CheckErr (createCmd .Flags ().MarkDeprecated ("config" ,
3840 "please see the command usage for more details." ))
3941
@@ -52,9 +54,9 @@ func init() {
5254}
5355
5456var (
55- bpFilename string
56- outputDir string
57- cliVariables []string
57+ bpFilenameDeprecated string
58+ outputDir string
59+ cliVariables []string
5860
5961 cliBEConfigVars []string
6062 overwriteDeployment bool
@@ -64,52 +66,114 @@ var (
6466 skipValidatorsDesc = "Validators to skip"
6567
6668 createCmd = & cobra.Command {
67- Use : "create BLUEPRINT_NAME" ,
68- Short : "Create a new deployment." ,
69- Long : "Create a new deployment based on a provided blueprint." ,
70- Run : runCreateCmd ,
71- Args : cobra .ExactArgs (1 ),
69+ Use : "create BLUEPRINT_NAME" ,
70+ Short : "Create a new deployment." ,
71+ Long : "Create a new deployment based on a provided blueprint." ,
72+ Run : runCreateCmd ,
73+ Args : cobra .ExactArgs (1 ),
74+ ValidArgsFunction : filterYaml ,
7275 }
7376)
7477
7578func runCreateCmd (cmd * cobra.Command , args []string ) {
76- if bpFilename == "" {
77- if len (args ) == 0 {
78- fmt .Println (cmd .UsageString ())
79- return
79+ dc := expandOrDie (args [0 ])
80+ if err := modulewriter .WriteDeployment (dc , outputDir , overwriteDeployment ); err != nil {
81+ var target * modulewriter.OverwriteDeniedError
82+ if errors .As (err , & target ) {
83+ fmt .Printf ("\n %s\n " , err .Error ())
84+ os .Exit (1 )
85+ } else {
86+ log .Fatal (err )
8087 }
81-
82- bpFilename = args [0 ]
8388 }
89+ }
8490
85- deploymentConfig , err := config .NewDeploymentConfig (bpFilename )
91+ func expandOrDie (path string ) config.DeploymentConfig {
92+ dc , err := config .NewDeploymentConfig (path )
8693 if err != nil {
8794 log .Fatal (err )
8895 }
89- if err := deploymentConfig .SetCLIVariables (cliVariables ); err != nil {
96+ // Set properties from CLI
97+ if err := setCLIVariables (& dc .Config , cliVariables ); err != nil {
9098 log .Fatalf ("Failed to set the variables at CLI: %v" , err )
9199 }
92- if err := deploymentConfig . SetBackendConfig ( cliBEConfigVars ); err != nil {
100+ if err := setBackendConfig ( & dc . Config , cliBEConfigVars ); err != nil {
93101 log .Fatalf ("Failed to set the backend config at CLI: %v" , err )
94102 }
95- if err := deploymentConfig . SetValidationLevel ( validationLevel ); err != nil {
103+ if err := setValidationLevel ( & dc . Config , validationLevel ); err != nil {
96104 log .Fatal (err )
97105 }
98- if err := skipValidators (& deploymentConfig ); err != nil {
106+ if err := skipValidators (& dc ); err != nil {
99107 log .Fatal (err )
100108 }
101- if err := deploymentConfig .ExpandConfig (); err != nil {
109+ if dc .Config .GhpcVersion != "" {
110+ fmt .Printf ("ghpc_version setting is ignored." )
111+ }
112+ dc .Config .GhpcVersion = GitCommitInfo
113+
114+ // Expand the blueprint
115+ if err := dc .ExpandConfig (); err != nil {
102116 log .Fatal (err )
103117 }
104- if err := modulewriter .WriteDeployment (deploymentConfig , outputDir , overwriteDeployment ); err != nil {
105- var target * modulewriter.OverwriteDeniedError
106- if errors .As (err , & target ) {
107- fmt .Printf ("\n %s\n " , err .Error ())
108- os .Exit (1 )
109- } else {
110- log .Fatal (err )
118+
119+ return dc
120+ }
121+
122+ func setCLIVariables (bp * config.Blueprint , s []string ) error {
123+ for _ , cliVar := range s {
124+ arr := strings .SplitN (cliVar , "=" , 2 )
125+
126+ if len (arr ) != 2 {
127+ return fmt .Errorf ("invalid format: '%s' should follow the 'name=value' format" , cliVar )
128+ }
129+ // Convert the variable's string literal to its equivalent default type.
130+ key := arr [0 ]
131+ var v config.YamlValue
132+ if err := yaml .Unmarshal ([]byte (arr [1 ]), & v ); err != nil {
133+ return fmt .Errorf ("invalid input: unable to convert '%s' value '%s' to known type" , key , arr [1 ])
111134 }
135+ bp .Vars .Set (key , v .Unwrap ())
112136 }
137+ return nil
138+ }
139+
140+ func setBackendConfig (bp * config.Blueprint , s []string ) error {
141+ if len (s ) == 0 {
142+ return nil // no op
143+ }
144+ be := config.TerraformBackend {Type : "gcs" }
145+ for _ , config := range s {
146+ arr := strings .SplitN (config , "=" , 2 )
147+
148+ if len (arr ) != 2 {
149+ return fmt .Errorf ("invalid format: '%s' should follow the 'name=value' format" , config )
150+ }
151+
152+ key , value := arr [0 ], arr [1 ]
153+ switch key {
154+ case "type" :
155+ be .Type = value
156+ default :
157+ be .Configuration .Set (key , cty .StringVal (value ))
158+ }
159+ }
160+ bp .TerraformBackendDefaults = be
161+ return nil
162+ }
163+
164+ // SetValidationLevel allows command-line tools to set the validation level
165+ func setValidationLevel (bp * config.Blueprint , s string ) error {
166+ switch s {
167+ case "ERROR" :
168+ bp .ValidationLevel = config .ValidationError
169+ case "WARNING" :
170+ bp .ValidationLevel = config .ValidationWarning
171+ case "IGNORE" :
172+ bp .ValidationLevel = config .ValidationIgnore
173+ default :
174+ return fmt .Errorf ("invalid validation level (\" ERROR\" , \" WARNING\" , \" IGNORE\" )" )
175+ }
176+ return nil
113177}
114178
115179func skipValidators (dc * config.DeploymentConfig ) error {
@@ -123,3 +187,10 @@ func skipValidators(dc *config.DeploymentConfig) error {
123187 }
124188 return nil
125189}
190+
191+ func filterYaml (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
192+ if len (args ) != 0 {
193+ return nil , cobra .ShellCompDirectiveNoFileComp
194+ }
195+ return []string {"yaml" , "yml" }, cobra .ShellCompDirectiveFilterFileExt
196+ }
0 commit comments