Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(init): add support for profile flag #1026

Merged
merged 15 commits into from
May 28, 2020
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -63,32 +63,41 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200511151306-5e35a6b50424 h1:daVeC8IxL9EA3ASo38uwQm2nGcprn0L0XMb8Sj5DL4Y=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200511151306-5e35a6b50424/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
16 changes: 10 additions & 6 deletions internal/core/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,12 @@ func Bootstrap(config *BootstrapConfig) (exitCode int, result interface{}, err e
}
interactive.SetOutputWriter(config.Stderr) // set printer for interactive function (always stderr).

// An authenticated client will be created later if required.
client := config.Client
isClientFromBootstrapConfig := true
if client == nil {
// Create scw client
client, err = createClient(config.BuildInfo, profileName)
isClientFromBootstrapConfig = false
client, err = createAnonymousClient(config.BuildInfo)
if err != nil {
printErr := globalPrinter.Print(err, nil)
if printErr != nil {
Expand All @@ -114,15 +116,17 @@ func Bootstrap(config *BootstrapConfig) (exitCode int, result interface{}, err e
ProfileFlag: profileName,
BinaryName: config.Args[0],
BuildInfo: config.BuildInfo,
stdout: config.Stdout,
stderr: config.Stderr,
Client: client,
Commands: config.Commands,
Printer: globalPrinter,
OverrideEnv: config.OverrideEnv,
OverrideExec: config.OverrideExec,
result: nil, // result is later injected by cobra_utils.go/cobraRun()
command: nil, // command is later injected by cobra_utils.go/cobraRun()

stdout: config.Stdout,
stderr: config.Stderr,
result: nil, // result is later injected by cobra_utils.go/cobraRun()
command: nil, // command is later injected by cobra_utils.go/cobraRun()
isClientFromBootstrapConfig: isClientFromBootstrapConfig,
}
// We make sure OverrideEnv is never nil in meta.
if meta.OverrideEnv == nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/core/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestInterruptError(t *testing.T) {
TestCheckStderrGolden(),
),
}))
t.Run("emtpy-success", Test(&TestConfig{
t.Run("empty-success", Test(&TestConfig{
Commands: NewCommands(
&Command{
Namespace: "test",
Expand All @@ -107,7 +107,7 @@ func TestInterruptError(t *testing.T) {
Cmd: "scw test empty success",
Check: TestCheckStdoutGolden(),
}))
t.Run("emtpy-success-json", Test(&TestConfig{
t.Run("empty-success-json", Test(&TestConfig{
Commands: NewCommands(
&Command{
Namespace: "test",
Expand Down
23 changes: 22 additions & 1 deletion internal/core/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ func createClient(buildInfo *BuildInfo, profileName string) (*scw.Client, error)
}

userAgent := "scaleway-cli/"
userAgent += buildInfo.Version.String()
if buildInfo.Version != nil {
remyleone marked this conversation as resolved.
Show resolved Hide resolved
userAgent += buildInfo.Version.String()
}
opts := []scw.ClientOption{
scw.WithDefaultRegion(scw.RegionFrPar),
scw.WithDefaultZone(scw.ZoneFrPar1),
Expand All @@ -73,6 +75,25 @@ func createClient(buildInfo *BuildInfo, profileName string) (*scw.Client, error)
return client, nil
}

func createAnonymousClient(buildInfo *BuildInfo) (*scw.Client, error) {
userAgent := "scaleway-cli-anonymous/"
if buildInfo.Version != nil {
userAgent += buildInfo.Version.String()
}
opts := []scw.ClientOption{
scw.WithDefaultRegion(scw.RegionFrPar),
scw.WithDefaultZone(scw.ZoneFrPar1),
scw.WithUserAgent(userAgent),
}

client, err := scw.NewClient(opts...)
if err != nil {
return nil, err
}

return client, nil
}

// configErrorDetails generate a detailed error message for an invalid client option.
func configErrorDetails(configKey, varEnv string) string {
// TODO: update the more info link
Expand Down
8 changes: 5 additions & 3 deletions internal/core/cobra_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ func cobraRun(ctx context.Context, cmd *Command) func(*cobra.Command, []string)
meta := extractMeta(ctx)
meta.command = cmd

// If command require a client we make sure a client is present with proper configuration
if !cmd.AllowAnonymousClient {
err := validateClient(meta.Client)
// If command requires authentication, we create a new client and overwrite the existing one
remyleone marked this conversation as resolved.
Show resolved Hide resolved
if !cmd.AllowAnonymousClient && !meta.isClientFromBootstrapConfig {
client, err := createClient(meta.BuildInfo, ExtractProfileName(ctx))
meta.Client = client
err = validateClient(meta.Client)
if err != nil {
return err
}
Expand Down
9 changes: 5 additions & 4 deletions internal/core/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ type meta struct {
OverrideEnv map[string]string
OverrideExec OverrideExecFunc

command *Command
stdout io.Writer
stderr io.Writer
result interface{}
command *Command
stdout io.Writer
stderr io.Writer
result interface{}
isClientFromBootstrapConfig bool
}

type contextKey int
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
remyleone marked this conversation as resolved.
Show resolved Hide resolved
67 changes: 38 additions & 29 deletions internal/namespaces/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,27 +241,28 @@ func initCommand() *core.Command {
}

// Ask whether to remove v1 configuration file if it exists
homeDir, err := os.UserHomeDir()
if err == nil {
configPath := path.Join(homeDir, ".scwrc")
if _, err := os.Stat(configPath); err == nil {
removeV1ConfigFile, err := interactive.PromptBoolWithConfig(&interactive.PromptBoolConfig{
Prompt: "Do you want to permanently remove old configuration file (" + configPath + ")?",
DefaultValue: false,
})
if err != nil {
return err
}
if args.RemoveV1Config == nil {
homeDir, err := os.UserHomeDir()
if err == nil {
configPath := path.Join(homeDir, ".scwrc")
if _, err := os.Stat(configPath); err == nil {
removeV1ConfigFile, err := interactive.PromptBoolWithConfig(&interactive.PromptBoolConfig{
Prompt: "Do you want to permanently remove old configuration file (" + configPath + ")?",
DefaultValue: false,
})
if err != nil {
return err
}

args.RemoveV1Config = &removeV1ConfigFile
args.RemoveV1Config = &removeV1ConfigFile
}
}
}

return nil
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
args := argsI.(*initArgs)

// Check if a config exists
// Creates a new one if it does not
config, err := scw.LoadConfig()
Expand All @@ -274,34 +275,42 @@ func initCommand() *core.Command {
config.SendTelemetry = args.SendTelemetry
}

// Update active profile
profile, err := config.GetActiveProfile()
if err != nil {
return nil, err
}
profile.SecretKey = &args.SecretKey
profile.DefaultZone = scw.StringPtr(args.Zone.String())
profile.DefaultRegion = scw.StringPtr(args.Region.String())
profile.DefaultOrganizationID = &args.OrganizationID
err = config.Save()
if err != nil {
return nil, err
}

// Get access key
accessKey, err := account.GetAccessKey(args.SecretKey)
if err != nil {
interactive.Printf("Config saved at %s:\n%s\n", scw.GetConfigPath(), terminal.Style(fmt.Sprint(config), color.Faint))
return "", &core.CliError{
Err: err,
Details: "Failed to retrieve Access Key for the given Secret Key.",
}
}
profile.AccessKey = &accessKey

profile := &scw.Profile{
AccessKey: &accessKey,
SecretKey: &args.SecretKey,
DefaultZone: scw.StringPtr(args.Zone.String()),
DefaultRegion: scw.StringPtr(args.Region.String()),
DefaultOrganizationID: &args.OrganizationID,
}
// Save the profile as default or as a named profile
profileName := core.ExtractProfileName(ctx)
_, err = config.GetProfile(profileName)
if profileName == "" || err == nil {
// Default configuration
config.Profile = *profile
} else {
if config.Profiles == nil {
config.Profiles = make(map[string]*scw.Profile)
}
config.Profiles[profileName] = profile
}

// Persist configuration on disk
interactive.Printf("Config saved at %s:\n%s\n", scw.GetConfigPath(), terminal.Style(fmt.Sprint(config), color.Faint))
err = config.Save()
if err != nil {
return nil, err
}

// Now that the config has been save we reload the client with the new config
err = core.ReloadClient(ctx)
if err != nil {
Expand Down