18
18
package config
19
19
20
20
import (
21
+ "errors"
22
+ "fmt"
21
23
"os"
24
+ "strings"
22
25
23
26
"github.com/arduino/arduino-cli/cli/errorcodes"
24
27
"github.com/arduino/arduino-cli/cli/feedback"
25
- "github.com/arduino/arduino-cloud-cli/command/config"
28
+ "github.com/arduino/arduino-cloud-cli/arduino"
29
+ "github.com/arduino/arduino-cloud-cli/internal/config"
30
+ "github.com/arduino/go-paths-helper"
31
+ "github.com/manifoldco/promptui"
26
32
"github.com/sirupsen/logrus"
27
33
"github.com/spf13/cobra"
34
+ "github.com/spf13/viper"
35
+ )
36
+
37
+ const (
38
+ clientIDLen = 32
39
+ clientSecretLen = 64
28
40
)
29
41
30
42
var initFlags struct {
@@ -36,32 +48,105 @@ var initFlags struct {
36
48
func initInitCommand () * cobra.Command {
37
49
initCommand := & cobra.Command {
38
50
Use : "init" ,
39
- Short : "Initialize a configuration file with default values " ,
40
- Long : "Initialize an Arduino IoT Cloud CLI configuration file with default values " ,
51
+ Short : "Initialize a configuration file" ,
52
+ Long : "Initialize an Arduino IoT Cloud CLI configuration" ,
41
53
Run : runInitCommand ,
42
54
}
43
55
44
- initCommand .Flags ().StringVar (& initFlags .destDir , "dest-dir" , ". " , "Sets where to save the configuration file. " )
45
- initCommand .Flags ().BoolVar (& initFlags .overwrite , "overwrite" , false , "Overwrite existing config file. " )
56
+ initCommand .Flags ().StringVar (& initFlags .destDir , "dest-dir" , "" , "Sets where to save the configuration file" )
57
+ initCommand .Flags ().BoolVar (& initFlags .overwrite , "overwrite" , false , "Overwrite existing config file" )
46
58
initCommand .Flags ().StringVar (& initFlags .format , "config-format" , "yaml" , "Format of the configuration file, can be {yaml|json}" )
47
59
48
60
return initCommand
49
61
}
50
62
51
63
func runInitCommand (cmd * cobra.Command , args []string ) {
52
- logrus .Infof ("Initializing a config file in folder: %s" , initFlags .destDir )
64
+ logrus .Info ("Initializing config file" )
65
+
66
+ // Get default destination directory if it's not passed
67
+ if initFlags .destDir == "" {
68
+ configPath , err := arduino .DataDir ()
69
+ if err != nil {
70
+ feedback .Errorf ("Error during config init: cannot retrieve arduino default directory: %v" , err )
71
+ os .Exit (errorcodes .ErrGeneric )
72
+ }
73
+ initFlags .destDir = configPath .String ()
74
+ }
75
+
76
+ // Validate format flag
77
+ initFlags .format = strings .ToLower (initFlags .format )
78
+ if initFlags .format != "json" && initFlags .format != "yaml" {
79
+ feedback .Error ("Error during config init: format is not valid, provide 'json' or 'yaml'" )
80
+ os .Exit (errorcodes .ErrGeneric )
81
+ }
53
82
54
- params := & config.InitParams {
55
- DestDir : initFlags .destDir ,
56
- Overwrite : initFlags .overwrite ,
57
- Format : initFlags .format ,
83
+ // Check that the destination directory is valid and build the configuration file path
84
+ configPath , err := paths .New (initFlags .destDir ).Abs ()
85
+ if err != nil {
86
+ feedback .Errorf ("Error during config init: cannot retrieve absolute path of %s: %v" , initFlags .destDir , err )
87
+ os .Exit (errorcodes .ErrGeneric )
88
+ }
89
+ if ! configPath .IsDir () {
90
+ feedback .Errorf ("Error during config init: %s is not a valid directory" , configPath )
91
+ os .Exit (errorcodes .ErrGeneric )
92
+ }
93
+ configFile := configPath .Join (config .Filename + "." + initFlags .format )
94
+ if ! initFlags .overwrite && configFile .Exist () {
95
+ feedback .Errorf ("Error during config init: %s already exists, use '--overwrite' to overwrite it" ,
96
+ configFile )
97
+ os .Exit (errorcodes .ErrGeneric )
58
98
}
59
99
60
- err := config .Init (params )
100
+ // Take needed configuration parameters starting an interactive mode
101
+ feedback .Print ("To obtain your API credentials visit https://create.arduino.cc/iot/integrations" )
102
+ id , key , err := paramsPrompt ()
61
103
if err != nil {
62
- feedback .Errorf ("Error during config init: %v" , err )
104
+ feedback .Errorf ("Error during config init: cannot take config params: %v" , err )
63
105
os .Exit (errorcodes .ErrGeneric )
64
106
}
65
107
66
- logrus .Info ("Config file successfully initialized" )
108
+ // Write the configuration file
109
+ newSettings := viper .New ()
110
+ newSettings .SetConfigPermissions (os .FileMode (0600 ))
111
+ newSettings .Set ("client" , id )
112
+ newSettings .Set ("secret" , key )
113
+ if err := newSettings .WriteConfigAs (configFile .String ()); err != nil {
114
+ feedback .Errorf ("Error during config init: cannot create config file: %v" , err )
115
+ os .Exit (errorcodes .ErrGeneric )
116
+ }
117
+
118
+ feedback .Printf ("Config file successfully initialized at: %s" , configFile )
119
+ }
120
+
121
+ func paramsPrompt () (id , key string , err error ) {
122
+ prompt := promptui.Prompt {
123
+ Label : "Please enter the Client ID" ,
124
+ Validate : func (s string ) error {
125
+ if len (s ) != clientIDLen {
126
+ return errors .New ("client-id not valid" )
127
+ }
128
+ return nil
129
+ },
130
+ }
131
+ id , err = prompt .Run ()
132
+ if err != nil {
133
+ return "" , "" , fmt .Errorf ("client prompt fail: %w" , err )
134
+ }
135
+
136
+ prompt = promptui.Prompt {
137
+ Mask : '*' ,
138
+ Label : "Please enter the Client Secret" ,
139
+ Validate : func (s string ) error {
140
+ if len (s ) != clientSecretLen {
141
+ return errors .New ("client secret not valid" )
142
+ }
143
+ return nil
144
+ },
145
+ }
146
+ key , err = prompt .Run ()
147
+ if err != nil {
148
+ return "" , "" , fmt .Errorf ("client secret prompt fail: %w" , err )
149
+ }
150
+
151
+ return id , key , nil
67
152
}
0 commit comments