@@ -25,60 +25,184 @@ import (
25
25
"github.com/spf13/viper"
26
26
)
27
27
28
+ const (
29
+ ClientIDLen = 32
30
+ ClientSecretLen = 64
31
+
32
+ EnvPrefix = "ARDUINO_CLOUD"
33
+ )
34
+
28
35
// Config contains all the configuration parameters
29
36
// known by arduino-cloud-cli.
30
37
type Config struct {
31
38
Client string `map-structure:"client"` // Client ID of the user
32
39
Secret string `map-structure:"secret"` // Secret ID of the user, unique for each Client ID
33
40
}
34
41
35
- // Retrieve returns the actual parameters contained in the
36
- // configuration file, if any. Returns error if no config file is found.
42
+ // Validate the config
43
+ // If config is not valid, it returns an error explaining the reason
44
+ func (c * Config ) Validate () error {
45
+ if len (c .Client ) != ClientIDLen {
46
+ return fmt .Errorf (
47
+ "client id not valid, expected len %d but got %d" ,
48
+ ClientIDLen ,
49
+ len (c .Client ),
50
+ )
51
+ }
52
+ if len (c .Secret ) != ClientSecretLen {
53
+ return fmt .Errorf (
54
+ "client secret not valid, expected len %d but got %d" ,
55
+ ClientSecretLen ,
56
+ len (c .Secret ),
57
+ )
58
+ }
59
+ return nil
60
+ }
61
+
62
+ // IsEmpty checks if config has no params set
63
+ func (c * Config ) IsEmpty () bool {
64
+ if len (c .Client ) != 0 {
65
+ return false
66
+ }
67
+ if len (c .Secret ) != 0 {
68
+ return false
69
+ }
70
+ return true
71
+ }
72
+
73
+ // Retrieve looks for configuration parameters in
74
+ // environment variables or in configuration file
75
+ // Returns error if no config is found
37
76
func Retrieve () (* Config , error ) {
77
+ // Config extracted from environment has highest priority
78
+ c , err := fromEnv ()
79
+ if err != nil {
80
+ return nil , fmt .Errorf ("reading config from environment variables: %w" , err )
81
+ }
82
+ // Return the config only if it has been found
83
+ if c != nil {
84
+ return c , nil
85
+ }
86
+
87
+ c , err = fromFile ()
88
+ if err != nil {
89
+ return nil , fmt .Errorf ("reading config from file: %w" , err )
90
+ }
91
+ if c != nil {
92
+ return c , nil
93
+ }
94
+
95
+ return nil , fmt .Errorf (
96
+ "config has not been found neither in environment variables " +
97
+ "nor in the current directory, its parents or in arduino15" ,
98
+ )
99
+ }
100
+
101
+ // fromFile looks for a configuration file
102
+ // If a config file is not found, it returns a nil config without raising errors.
103
+ // If invalid config file is found, it returns an error.
104
+ func fromFile () (* Config , error ) {
105
+ // Looks for a configuration file
38
106
configDir , err := searchConfigDir ()
39
107
if err != nil {
40
108
return nil , fmt .Errorf ("can't get config directory: %w" , err )
41
109
}
110
+ // Return nil config if no config file is found
111
+ if configDir == nil {
112
+ return nil , nil
113
+ }
42
114
43
115
v := viper .New ()
44
116
v .SetConfigName (Filename )
45
- v .AddConfigPath (configDir )
117
+ v .AddConfigPath (* configDir )
46
118
err = v .ReadInConfig ()
47
119
if err != nil {
48
- err = fmt .Errorf ("%s: %w" , "retrieving config file" , err )
120
+ err = fmt .Errorf (
121
+ "config file found at %s but cannot read its content: %w" ,
122
+ * configDir ,
123
+ err ,
124
+ )
49
125
return nil , err
50
126
}
51
127
52
128
conf := & Config {}
53
- v .Unmarshal (conf )
129
+ err = v .Unmarshal (conf )
130
+ if err != nil {
131
+ return nil , fmt .Errorf (
132
+ "config file found at %s but cannot unmarshal it: %w" ,
133
+ * configDir ,
134
+ err ,
135
+ )
136
+ }
137
+ if err = conf .Validate (); err != nil {
138
+ return nil , fmt .Errorf (
139
+ "config file found at %s but is not valid: %w" ,
140
+ * configDir ,
141
+ err ,
142
+ )
143
+ }
144
+ return conf , nil
145
+ }
146
+
147
+ // fromEnv looks for configuration credentials in environment variables.
148
+ // If credentials are not found, it returns a nil config without raising errors.
149
+ // If invalid credentials are found, it returns an error.
150
+ func fromEnv () (* Config , error ) {
151
+ v := viper .New ()
152
+ SetDefaults (v )
153
+ v .SetEnvPrefix ("ARDUINO_CLOUD" )
154
+ v .AutomaticEnv ()
155
+
156
+ conf := & Config {}
157
+ err := v .Unmarshal (conf )
158
+ if err != nil {
159
+ return nil , fmt .Errorf ("cannot unmarshal config from environment variables: %w" , err )
160
+ }
161
+
162
+ if conf .IsEmpty () {
163
+ return nil , nil
164
+ }
165
+
166
+ if err = conf .Validate (); err != nil {
167
+ return nil , fmt .Errorf (
168
+ "config retrieved from environment variables with prefix '%s' are not valid: %w" ,
169
+ EnvPrefix ,
170
+ err ,
171
+ )
172
+ }
54
173
return conf , nil
55
174
}
56
175
57
- func searchConfigDir () (string , error ) {
176
+ // searchConfigDir configuration file in different directories in the following order:
177
+ // current working directory, parents of the current working directory, arduino15 default directory
178
+ // Returns a nil string if no config file has been found, without raising errors
179
+ // Returns an error if any problem is encountered during the file research which prevents
180
+ // to understand whether a config file exists or not
181
+ func searchConfigDir () (* string , error ) {
58
182
// Search in current directory and its parents.
59
183
cwd , err := paths .Getwd ()
60
184
if err != nil {
61
- return "" , err
185
+ return nil , err
62
186
}
63
187
// Don't let bad naming mislead you, cwd.Parents()[0] is cwd itself so
64
188
// we look in the current directory first and then on its parents.
65
189
for _ , path := range cwd .Parents () {
66
190
if path .Join (Filename + ".yaml" ).Exist () || path .Join (Filename + ".json" ).Exist () {
67
- return path .String (), nil
191
+ p := path .String ()
192
+ return & p , nil
68
193
}
69
194
}
70
195
71
196
// Search in arduino's default data directory.
72
197
arduino15 , err := arduino .DataDir ()
73
198
if err != nil {
74
- return "" , err
199
+ return nil , err
75
200
}
76
201
if arduino15 .Join (Filename + ".yaml" ).Exist () || arduino15 .Join (Filename + ".json" ).Exist () {
77
- return arduino15 .String (), nil
202
+ p := arduino15 .String ()
203
+ return & p , nil
78
204
}
79
205
80
- return "" , fmt .Errorf (
81
- "didn't find config file in the current directory, its parents or in %s" ,
82
- arduino15 .String (),
83
- )
206
+ // Didn't find config file in the current directory, its parents or in arduino15"
207
+ return nil , nil
84
208
}
0 commit comments