Skip to content

Commit

Permalink
feat(config): add profile activate command (#1206)
Browse files Browse the repository at this point in the history
  • Loading branch information
jerome-quere authored Jul 13, 2020
1 parent 59677b5 commit 4216b26
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟥🟥🟥 STDERR️️ 🟥🟥🟥️
Mark a profile as active in the config file

USAGE:
scw config profile activate <profile-name ...> [arg=value ...]

ARGS:
profile-name

FLAGS:
-h, --help help for activate

GLOBAL FLAGS:
-c, --config string The path to the config file
-D, --debug Enable debug mode
-o, --output string Output format: json or human, see 'scw help output' for more info (default "human")
-p, --profile string The config profile to use
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ USAGE:
scw config profile <command>

AVAILABLE COMMANDS:
activate Mark a profile as active in the config file
delete Delete a profile from the config file

FLAGS:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/mattn/go-colorable v0.1.4
github.com/mattn/go-isatty v0.0.11
github.com/pkg/errors v0.9.1 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200707130522-abc4aeb2a4e6
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200710161155-10382899255f
github.com/sergi/go-diff v1.0.0 // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200624111939-0a4e128e532e
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200624111939-0a4e128e532e/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200707130522-abc4aeb2a4e6 h1:mCYMQVdy3ciDx7jtDnRuxTk9IUB525PhZYkCTjMWQUI=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200707130522-abc4aeb2a4e6/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200710161155-10382899255f h1:FHSh2peVlKEecLqHX/8uevrWqeua68LbVBOzIhC0HBw=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200710161155-10382899255f/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=
Expand Down
30 changes: 30 additions & 0 deletions internal/core/autocomplete_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package core

import (
"context"
"strings"

"github.com/scaleway/scaleway-sdk-go/scw"
)

func AutocompleteProfileName() AutoCompleteArgFunc {
return func(ctx context.Context, prefix string) AutocompleteSuggestions {
res := AutocompleteSuggestions(nil)
configPath := ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err != nil {
return res
}

for profileName := range config.Profiles {
if strings.HasPrefix(profileName, prefix) {
res = append(res, profileName)
}
}

if strings.HasPrefix(scw.DefaultProfileName, prefix) {
res = append(res, scw.DefaultProfileName)
}
return res
}
}
15 changes: 3 additions & 12 deletions internal/core/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,9 @@ func createClient(httpClient *http.Client, buildInfo *BuildInfo, profileName str
return nil, err
}

var activeProfile *scw.Profile

if profileName != "" {
activeProfile, err = config.GetProfile(profileName)
if err != nil {
return nil, err
}
} else {
activeProfile, err = config.GetActiveProfile()
if err != nil {
return nil, err
}
activeProfile, err := config.GetProfile(profileName)
if err != nil {
return nil, err
}

envProfile := scw.LoadEnvProfile()
Expand Down
19 changes: 17 additions & 2 deletions internal/core/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,25 @@ func ExtractStdin(ctx context.Context) io.Reader {
}

func ExtractProfileName(ctx context.Context) string {
// Handle profile flag -p
if extractMeta(ctx).ProfileFlag != "" {
return extractMeta(ctx).ProfileFlag
}
return ExtractEnv(ctx, scw.ScwActiveProfileEnv)

// Handle SCW_PROFILE env variable
if env := ExtractEnv(ctx, scw.ScwActiveProfileEnv); env != "" {
return env
}

// Handle active_profile in config file
configPath := ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err == nil && config.ActiveProfile != nil {
return *config.ActiveProfile
}

// Return default profile name
return scw.DefaultProfileName
}

func ExtractHTTPClient(ctx context.Context) *http.Client {
Expand All @@ -139,7 +154,7 @@ func ReloadClient(ctx context.Context) error {
if meta.isClientFromBootstrapConfig {
return nil
}
meta.Client, err = createClient(meta.httpClient, meta.BuildInfo, "")
meta.Client, err = createClient(meta.httpClient, meta.BuildInfo, ExtractProfileName(ctx))
return err
}

Expand Down
75 changes: 61 additions & 14 deletions internal/namespaces/config/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"context"
"fmt"
"path"
"reflect"

"github.com/scaleway/scaleway-sdk-go/validation"
Expand All @@ -27,6 +26,7 @@ func GetCommands() *core.Commands {
configDumpCommand(),
configProfileCommand(),
configDeleteProfileCommand(),
configActivateProfileCommand(),
configResetCommand(),
)
}
Expand Down Expand Up @@ -128,7 +128,7 @@ func configGetCommand() *core.Command {
},
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
config, err := scw.LoadConfigFromPath(extractConfigPath(ctx))
config, err := scw.LoadConfigFromPath(core.ExtractConfigPath(ctx))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -254,7 +254,7 @@ The only allowed attributes are access_key, secret_key, default_organization_id,
args := argsI.(*scw.Profile)

// Execute
configPath := extractConfigPath(ctx)
configPath := core.ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err != nil {
return nil, err
Expand All @@ -263,7 +263,7 @@ The only allowed attributes are access_key, secret_key, default_organization_id,
// send_telemetry is the only key that is not in a profile but in the config object directly
profileName := core.ExtractProfileName(ctx)
profile := &config.Profile
if profileName != "" {
if profileName != scw.DefaultProfileName {
var exist bool
profile, exist = config.Profiles[profileName]
if !exist {
Expand Down Expand Up @@ -319,7 +319,7 @@ func configUnsetCommand() *core.Command {
},
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
configPath := extractConfigPath(ctx)
configPath := core.ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err != nil {
return nil, err
Expand Down Expand Up @@ -365,7 +365,7 @@ func configDumpCommand() *core.Command {
},
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
configPath := extractConfigPath(ctx)
configPath := core.ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err != nil {
return nil, err
Expand Down Expand Up @@ -406,7 +406,7 @@ func configDeleteProfileCommand() *core.Command {
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
profileName := argsI.(*configDeleteProfileArgs).Name
configPath := extractConfigPath(ctx)
configPath := core.ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err != nil {
return nil, err
Expand All @@ -428,6 +428,56 @@ func configDeleteProfileCommand() *core.Command {
}
}

// configActivateProfileCommand mark a profile as active
func configActivateProfileCommand() *core.Command {
type configActiveProfileArgs struct {
ProfileName string
}

return &core.Command{
Short: `Mark a profile as active in the config file`,
Namespace: "config",
Resource: "profile",
Verb: "activate",
AllowAnonymousClient: true,
ArgsType: reflect.TypeOf(configActiveProfileArgs{}),
ArgSpecs: core.ArgSpecs{
{
Name: "profile-name",
Required: true,
Positional: true,
AutoCompleteFunc: core.AutocompleteProfileName(),
},
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
profileName := argsI.(*configActiveProfileArgs).ProfileName
configPath := core.ExtractConfigPath(ctx)
config, err := scw.LoadConfigFromPath(configPath)
if err != nil {
return nil, err
}

if profileName == scw.DefaultProfileName {
config.ActiveProfile = nil
} else {
if _, exists := config.Profiles[profileName]; !exists {
return nil, unknownProfileError(profileName)
}
config.ActiveProfile = &profileName
}

err = config.SaveTo(configPath)
if err != nil {
return nil, err
}

return &core.SuccessResult{
Message: fmt.Sprintf("successfully activate profile %s", profileName),
}, nil
},
}
}

// configResetCommand resets the config
func configResetCommand() *core.Command {
type configResetArgs struct{}
Expand Down Expand Up @@ -498,14 +548,11 @@ func getProfileKeys() []string {
return keys
}

// This func should be removes when core implement it
func extractConfigPath(ctx context.Context) string {
homeDir := core.ExtractUserHomeDir(ctx)
return path.Join(homeDir, ".config", "scw", "config.yaml")
}

// getProfile return a config profile by its name.
// Warning: This return the profile pointer directly so it can be modified by commands.
// For this reason we cannot rely on config.GetProfileByName method as it create a copy.
func getProfile(config *scw.Config, profileName string) (*scw.Profile, error) {
if profileName == "" {
if profileName == scw.DefaultProfileName {
return &config.Profile, nil
}
profile, exist := config.Profiles[profileName]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,31 @@ profiles:

🟩🟩🟩 JSON STDOUT 🟩🟩🟩
{
"AccessKey": "SCWXXXXXXXXXXXXXXXXX",
"SecretKey": "11111111-1111-1111-1111-111111111111",
"APIURL": null,
"Insecure": true,
"DefaultOrganizationID": "11111111-1111-1111-1111-111111111111",
"DefaultProjectID": null,
"DefaultRegion": "fr-par",
"DefaultZone": "fr-par-1",
"SendTelemetry": true,
"ActiveProfile": null,
"Profiles": {
"access_key": "SCWXXXXXXXXXXXXXXXXX",
"secret_key": "11111111-1111-1111-1111-111111111111",
"insecure": true,
"default_organization_id": "11111111-1111-1111-1111-111111111111",
"default_region": "fr-par",
"default_zone": "fr-par-1",
"send_telemetry": true,
"profiles": {
"p1": {
"AccessKey": "SCWP1XXXXXXXXXXXXXXX",
"SecretKey": "11111111-1111-1111-1111-111111111111",
"APIURL": "https://p1-mock-api-url.com",
"Insecure": true,
"DefaultOrganizationID": "11111111-1111-1111-1111-111111111111",
"DefaultProjectID": null,
"DefaultRegion": "fr-par",
"DefaultZone": "fr-par-1",
"SendTelemetry": null
"access_key": "SCWP1XXXXXXXXXXXXXXX",
"secret_key": "11111111-1111-1111-1111-111111111111",
"api_url": "https://p1-mock-api-url.com",
"insecure": true,
"default_organization_id": "11111111-1111-1111-1111-111111111111",
"default_region": "fr-par",
"default_zone": "fr-par-1"
},
"p2": {
"AccessKey": "SCWP2XXXXXXXXXXXXXXX",
"SecretKey": "11111111-1111-1111-1111-111111111111",
"APIURL": "https://p2-mock-api-url.com",
"Insecure": true,
"DefaultOrganizationID": "11111111-1111-1111-1111-111111111111",
"DefaultProjectID": null,
"DefaultRegion": "fr-par",
"DefaultZone": "fr-par-1",
"SendTelemetry": null
"access_key": "SCWP2XXXXXXXXXXXXXXX",
"secret_key": "11111111-1111-1111-1111-111111111111",
"api_url": "https://p2-mock-api-url.com",
"insecure": true,
"default_organization_id": "11111111-1111-1111-1111-111111111111",
"default_region": "fr-par",
"default_zone": "fr-par-1"
}
}
}
8 changes: 6 additions & 2 deletions internal/namespaces/info/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func infosRoot() *core.Command {
BuildInfo: core.ExtractBuildInfo(ctx),
Settings: []*setting{
configPath(ctx),
profile(ctx),
profile(ctx, config),
defaultRegion(ctx, config, profileName),
defaultZone(ctx, config, profileName),
defaultOrganizationID(ctx, config, profileName),
Expand Down Expand Up @@ -105,18 +105,22 @@ func configPath(ctx context.Context) *setting {
return setting
}

func profile(ctx context.Context) *setting {
func profile(ctx context.Context, config *scw.Config) *setting {
setting := &setting{
Key: "profile",
Value: core.ExtractProfileName(ctx),
}

switch {
case core.ExtractProfileFlag(ctx) != "":
setting.Origin = "flag --profile/-p"
setting.Value = core.ExtractProfileFlag(ctx)
case core.ExtractEnv(ctx, scw.ScwActiveProfileEnv) != "":
setting.Origin = fmt.Sprintf("env (%s)", scw.ScwActiveProfileEnv)
setting.Value = core.ExtractEnv(ctx, scw.ScwActiveProfileEnv)
case config != nil && config.ActiveProfile != nil:
setting.Origin = "active_profile in config file"
setting.Value = *config.ActiveProfile
default:
setting.Origin = ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ GoOS runtime.GOOS
Settings:
KEY VALUE ORIGIN
config_path /tmp/.config/scw/config.yaml env (SCW_CONFIG_PATH)
profile - -
profile default -
default_region fr-par env (SCW_DEFAULT_REGION)
default_zone fr-par-1 env (SCW_DEFAULT_ZONE)
default_organization_id 22222222-2222-2222-2222-222222222222 env (SCW_DEFAULT_ORGANIZATION_ID)
Expand All @@ -37,7 +37,7 @@ secret_key 22222222-2222-2222-2222-222222222222 env (SCW_SECRET_K
},
{
"key": "profile",
"value": "",
"value": "default",
"origin": ""
},
{
Expand Down
Loading

0 comments on commit 4216b26

Please sign in to comment.