Skip to content

Commit 86b69d2

Browse files
author
Paolo Calao
authored
Refactor config init command (#68)
- use arduino15 directory by default for 'config init' - 'config init' command prompts the user to insert client-id and client-secret
1 parent 68a4aa2 commit 86b69d2

File tree

5 files changed

+158
-95
lines changed

5 files changed

+158
-95
lines changed

Diff for: arduino/dir.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// This file is part of arduino-cloud-cli.
2+
//
3+
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
package arduino
19+
20+
import (
21+
"fmt"
22+
"os"
23+
"path/filepath"
24+
"runtime"
25+
26+
"github.com/arduino/go-paths-helper"
27+
"github.com/arduino/go-win32-utils"
28+
)
29+
30+
// DataDir returns the Arduino default data directory (arduino15)
31+
func DataDir() (*paths.Path, error) {
32+
userHomeDir, err := os.UserHomeDir()
33+
if err != nil {
34+
return nil, fmt.Errorf("unable to get user home dir: %w", err)
35+
}
36+
37+
var path *paths.Path
38+
switch runtime.GOOS {
39+
case "darwin":
40+
path = paths.New(filepath.Join(userHomeDir, "Library", "Arduino15"))
41+
case "windows":
42+
localAppDataPath, err := win32.GetLocalAppDataFolder()
43+
if err != nil {
44+
return nil, fmt.Errorf("unable to get local app data folder: %w", err)
45+
}
46+
path = paths.New(filepath.Join(localAppDataPath, "Arduino15"))
47+
default: // linux, android, *bsd, plan9 and other Unix-like systems
48+
path = paths.New(filepath.Join(userHomeDir, ".arduino15"))
49+
}
50+
51+
return path, nil
52+
}

Diff for: cli/config/init.go

+98-13
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,25 @@
1818
package config
1919

2020
import (
21+
"errors"
22+
"fmt"
2123
"os"
24+
"strings"
2225

2326
"github.com/arduino/arduino-cli/cli/errorcodes"
2427
"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"
2632
"github.com/sirupsen/logrus"
2733
"github.com/spf13/cobra"
34+
"github.com/spf13/viper"
35+
)
36+
37+
const (
38+
clientIDLen = 32
39+
clientSecretLen = 64
2840
)
2941

3042
var initFlags struct {
@@ -36,32 +48,105 @@ var initFlags struct {
3648
func initInitCommand() *cobra.Command {
3749
initCommand := &cobra.Command{
3850
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",
4153
Run: runInitCommand,
4254
}
4355

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")
4658
initCommand.Flags().StringVar(&initFlags.format, "config-format", "yaml", "Format of the configuration file, can be {yaml|json}")
4759

4860
return initCommand
4961
}
5062

5163
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+
}
5382

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)
5898
}
5999

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()
61103
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)
63105
os.Exit(errorcodes.ErrGeneric)
64106
}
65107

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
67152
}

Diff for: command/config/init.go

-76
This file was deleted.

Diff for: go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ require (
66
github.com/antihax/optional v1.0.0
77
github.com/arduino/arduino-cli v0.0.0-20210607095659-16f41352eac3
88
github.com/arduino/go-paths-helper v1.6.1
9+
github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b
910
github.com/arduino/iot-client-go v1.3.4-0.20211116175324-9a98dd4ad269
1011
github.com/gofrs/uuid v4.0.0+incompatible
1112
github.com/google/go-cmp v0.5.6
1213
github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6
1314
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5
15+
github.com/manifoldco/promptui v0.9.0
1416
github.com/sirupsen/logrus v1.8.1
1517
github.com/spf13/cobra v1.1.3
1618
github.com/spf13/viper v1.7.0

Diff for: go.sum

+6-6
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ github.com/arduino/go-properties-orderedmap v1.3.0/go.mod h1:DKjD2VXY/NZmlingh4l
6060
github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b/go.mod h1:uwGy5PpN4lqW97FiLnbcx+xx8jly5YuPMJWfVwwjJiQ=
6161
github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b h1:3PjgYG5gVPA7cipp7vIR2lF96KkEJIFBJ+ANnuv6J20=
6262
github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b/go.mod h1:iIPnclBMYm1g32Q5kXoqng4jLhMStReIP7ZxaoUC2y8=
63-
github.com/arduino/iot-client-go v1.3.4-0.20211103115604-d4d372164262 h1:qVq8cdkaRPaLc9DAjY/6rH3ocs6ZvnEJtD26f5++/RU=
64-
github.com/arduino/iot-client-go v1.3.4-0.20211103115604-d4d372164262/go.mod h1:gYvpMt7Qw+OSScTLyIlCnpbvy9y96ey/2zhB4w6FoK0=
6563
github.com/arduino/iot-client-go v1.3.4-0.20211116175324-9a98dd4ad269 h1:01RHB48b1QRN5viXtdtmSkvyudxHqczDV+OD+1PuE6M=
6664
github.com/arduino/iot-client-go v1.3.4-0.20211116175324-9a98dd4ad269/go.mod h1:gYvpMt7Qw+OSScTLyIlCnpbvy9y96ey/2zhB4w6FoK0=
6765
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -76,8 +74,11 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
7674
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
7775
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
7876
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
77+
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
7978
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
79+
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
8080
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
81+
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
8182
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
8283
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
8384
github.com/cmaglie/go.rice v1.0.3 h1:ZBLmBdQp6ejc+n8eMNH0uuRSKkg6kKe6ORjXKnyHBYw=
@@ -272,6 +273,8 @@ github.com/leonelquinteros/gotext v1.4.0/go.mod h1:yZGXREmoGTtBvZHNcc+Yfug49G/2s
272273
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
273274
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
274275
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
276+
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
277+
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
275278
github.com/marcinbor85/gohex v0.0.0-20210308104911-55fb1c624d84/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
276279
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
277280
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
@@ -499,17 +502,13 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
499502
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
500503
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
501504
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
502-
golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 h1:VrJZAjbekhoRn7n5FBujY31gboH+iB3pdLxn3gE9FjU=
503-
golang.org/x/net v0.0.0-20211101193420-4a448f8816b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
504505
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
505506
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
506507
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
507508
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
508509
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
509510
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
510511
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
511-
golang.org/x/oauth2 v0.0.0-20211028175245-ba495a64dcb5 h1:v79phzBz03tsVCUTbvTBmmC3CUXF5mKYt7DA4ZVldpM=
512-
golang.org/x/oauth2 v0.0.0-20211028175245-ba495a64dcb5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
513512
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
514513
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
515514
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -528,6 +527,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
528527
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
529528
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
530529
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
530+
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
531531
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
532532
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
533533
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

0 commit comments

Comments
 (0)