diff --git a/go.mod b/go.mod index 504feb4c52..ad431f1f10 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,9 @@ require ( github.com/alecthomas/assert v1.0.0 github.com/buildpacks/pack v0.30.0-pre1.0.20230418191058-1190b6c52128 github.com/c-bata/go-prompt v0.2.6 + github.com/charmbracelet/bubbletea v0.24.1 github.com/chzyer/readline v1.5.1 - github.com/containerd/console v1.0.3 + github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 github.com/dnaeon/go-vcr v1.2.0 github.com/docker/docker v24.0.2+incompatible github.com/dustin/go-humanize v1.0.1 @@ -70,6 +71,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.18.9 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230322223720-077b4a917a90 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/buildpacks/imgutil v0.0.0-20230420161652-580610d0124b // indirect github.com/buildpacks/lifecycle v0.17.0-pre.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect @@ -115,6 +117,7 @@ require ( github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.16.5 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-tty v0.0.4 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -124,6 +127,10 @@ require ( github.com/moby/sys/signal v0.7.0 // indirect github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/reflow v0.3.0 // indirect + github.com/muesli/termenv v0.15.1 // indirect github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/opencontainers/runc v1.1.6 // indirect github.com/opencontainers/selinux v1.11.0 // indirect diff --git a/go.sum b/go.sum index 2accecd11b..8e3839f0cb 100644 --- a/go.sum +++ b/go.sum @@ -141,6 +141,8 @@ github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230322223720-077b4a917a90 h1:GN8SzriwBUX5aagQft8cJ5sKUaXdHUdX8q2gS2mkom8= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230322223720-077b4a917a90/go.mod h1:V97RBAXo2x0elgRWnSfhWLDkwwEl7dNmmBRAvbwmEoA= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/buildpacks/imgutil v0.0.0-20230420161652-580610d0124b h1:TsOLD4J7TcHQ7aaEYTDd+nEMSku3vPqq6UIyOR8IG9Q= github.com/buildpacks/imgutil v0.0.0-20230420161652-580610d0124b/go.mod h1:hgxVR7UpPvT5gATbRGM582oy048sUocDg6R6PMWAxow= @@ -154,6 +156,8 @@ github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/bubbletea v0.24.1 h1:LpdYfnu+Qc6XtvMz6d/6rRY71yttHTP5HtrjMgWvixc= +github.com/charmbracelet/bubbletea v0.24.1/go.mod h1:rK3g/2+T8vOSEkNHvtq40umJpeVYDn6bLaqbgzhL/hg= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -177,8 +181,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg= github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc= github.com/containerd/continuity v0.3.1-0.20230206214859-2a963a2f56e8 h1:EdSQb65ohzz4jsyPOhxfu3/+c9nnU0euk0otferwl9A= @@ -412,9 +416,12 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= @@ -441,6 +448,14 @@ github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbD github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= +github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -471,6 +486,7 @@ github.com/quantumsheep/pack v0.30.0-pre1.0.20230505095233-37158bb223a4 h1:1NPuV github.com/quantumsheep/pack v0.30.0-pre1.0.20230505095233-37158bb223a4/go.mod h1:JFPC0K0VzwZVW78VPN/CDD34lhTIpdAlR/zu+WhpnnM= github.com/rivo/tview v0.0.0-20230406072732-e22ce9588bb4 h1:zX+lRcFRPX1jn8A11jxT0dEQhkmUM7pec+9NLK8MiTQ= github.com/rivo/tview v0.0.0-20230406072732-e22ce9588bb4/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= diff --git a/internal/core/testing.go b/internal/core/testing.go index c453983851..fedf126dfb 100644 --- a/internal/core/testing.go +++ b/internal/core/testing.go @@ -599,6 +599,10 @@ type GoldenReplacement struct { // This is the format for repl in (*regexp.Regexp).ReplaceAll // You can use $ to represent groups $1, $2... Replacement string + + // OptionalMatch allow the golden to not contain the given patterns + // if false, the golden must contain the given pattern + OptionalMatch bool } // goldenReplacePatterns replace the list of patterns with their given replacement @@ -608,7 +612,9 @@ func goldenReplacePatterns(golden string, replacements ...GoldenReplacement) (st for _, replacement := range replacements { if !replacement.Pattern.MatchString(changedGolden) { - matchFailed = append(matchFailed, replacement.Pattern.String()) + if !replacement.OptionalMatch { + matchFailed = append(matchFailed, replacement.Pattern.String()) + } continue } changedGolden = replacement.Pattern.ReplaceAllString(changedGolden, replacement.Replacement) diff --git a/internal/interactive/list.go b/internal/interactive/list.go new file mode 100644 index 0000000000..4ea2025468 --- /dev/null +++ b/internal/interactive/list.go @@ -0,0 +1,94 @@ +//go:build !wasm + +package interactive + +import ( + "context" + "fmt" + "os" + + tea "github.com/charmbracelet/bubbletea" +) + +type ListPrompt struct { + // Prompt that will be printed when showing the list + Prompt string + Choices []string + // DefaultIndex is the element that will be selected when starting prompt + DefaultIndex int + + cursor int + cancelled bool +} + +func (m *ListPrompt) Init() tea.Cmd { + return nil +} + +func (m *ListPrompt) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + // Key is pressed + case tea.KeyMsg: + switch msg.String() { + case "ctrl+c", "q": + m.cancelled = true + return m, tea.Quit + case "up", "k": + if m.cursor > 0 { + m.cursor-- + } + case "down", "j": + if m.cursor < len(m.Choices)-1 { + m.cursor++ + } + case "enter", " ": + return m, tea.Quit + } + } + + return m, nil +} + +func (m *ListPrompt) View() string { + s := m.Prompt + "\n\n" + + for i, choice := range m.Choices { + if m.cursor == i { + s += fmt.Sprintf("> %s\n", choice) + } else { + s += fmt.Sprintf("%s\n", choice) + } + } + + s += "\nPress enter or space for select.\n" + + return s +} + +// Execute start the prompt and return the selected index +func (m *ListPrompt) Execute(ctx context.Context) (int, error) { + m.cursor = m.DefaultIndex + + opts := []tea.ProgramOption{ + tea.WithContext(ctx), + } + + if hasMockedResponse(ctx) { + opts = append(opts, tea.WithInput(&mockResponseReader{ + ctx: ctx, + defaultReader: os.Stdin, + })) + } + + p := tea.NewProgram(m, opts...) + _, err := p.Run() + if err != nil { + return -1, fmt.Errorf("error running prompt: %w", err) + } + + if m.cancelled { + return -1, fmt.Errorf("prompt cancelled") + } + + return m.cursor, nil +} diff --git a/internal/interactive/list_disabled.go b/internal/interactive/list_disabled.go new file mode 100644 index 0000000000..ca7796795a --- /dev/null +++ b/internal/interactive/list_disabled.go @@ -0,0 +1,18 @@ +//go:build wasm + +package interactive + +import ( + "context" + "fmt" +) + +type ListPrompt struct { + Prompt string + Choices []string + DefaultIndex int +} + +func (m *ListPrompt) Execute(ctx context.Context) (int, error) { + return -1, fmt.Errorf("not implemented for current platform") +} diff --git a/internal/interactive/test.go b/internal/interactive/test.go index 438e8a25fc..8c78110dfd 100644 --- a/internal/interactive/test.go +++ b/internal/interactive/test.go @@ -33,6 +33,10 @@ func popMockResponseFromContext(ctx context.Context) (string, bool) { return str, true } +func hasMockedResponse(ctx context.Context) bool { + return ctx.Value(contextKey) != nil +} + type mockResponseReader struct { ctx context.Context defaultReader io.ReadCloser diff --git a/internal/namespaces/init/init.go b/internal/namespaces/init/init.go index 309fbab129..4213306781 100644 --- a/internal/namespaces/init/init.go +++ b/internal/namespaces/init/init.go @@ -170,10 +170,7 @@ Default path for configuration file is based on the following priority order: if args.ProjectID == "" { args.ProjectID = getAPIKeyDefaultProjectID(ctx, args.AccessKey, args.SecretKey) - } - - if args.ProjectID == "" { - args.ProjectID, err = promptProjectID(ctx) + args.ProjectID, err = promptProjectID(ctx, args.AccessKey, args.SecretKey, args.OrganizationID, args.ProjectID) if err != nil { return nil, err } diff --git a/internal/namespaces/init/init_test.go b/internal/namespaces/init/init_test.go index dfdae3c312..850007d630 100644 --- a/internal/namespaces/init/init_test.go +++ b/internal/namespaces/init/init_test.go @@ -3,6 +3,7 @@ package init import ( "fmt" "path" + "regexp" "testing" "github.com/alecthomas/assert" @@ -198,3 +199,48 @@ func TestInit(t *testing.T) { })) }) } + +func TestInit_Prompt(t *testing.T) { + promptResponse := []string{ + "secret-key", + "access-key", + "organization-id", + " ", + } + + t.Run("Simple", core.Test(&core.TestConfig{ + Commands: GetCommands(), + BeforeFunc: core.BeforeFuncCombine( + baseBeforeFunc(), + func(ctx *core.BeforeFuncCtx) error { + promptResponse[0] = ctx.Meta["SecretKey"].(string) + promptResponse[1] = ctx.Meta["AccessKey"].(string) + promptResponse[2] = ctx.Meta["OrganizationID"].(string) + + return nil + }), + TmpHomeDir: true, + Cmd: "scw init", + Check: core.TestCheckCombine( + core.TestCheckGoldenAndReplacePatterns( + core.GoldenReplacement{ + Pattern: regexp.MustCompile("\\s\\sExcept for autocomplete: unsupported OS 'windows'\n"), + Replacement: "", + OptionalMatch: true, + }, + core.GoldenReplacement{ + Pattern: regexp.MustCompile(`Except for autocomplete: unsupported OS 'windows'\\n`), + Replacement: "", + OptionalMatch: true, + }, + ), + checkConfig(func(t *testing.T, ctx *core.CheckFuncCtx, config *scw.Config) { + secretKey, _ := ctx.Client.GetSecretKey() + assert.Equal(t, secretKey, *config.SecretKey) + assert.NotEmpty(t, *config.DefaultProjectID) + assert.Equal(t, *config.DefaultProjectID, *config.DefaultProjectID) + }), + ), + PromptResponseMocks: promptResponse, + })) +} diff --git a/internal/namespaces/init/prompt.go b/internal/namespaces/init/prompt.go index 3d3dc65aac..913283ea84 100644 --- a/internal/namespaces/init/prompt.go +++ b/internal/namespaces/init/prompt.go @@ -5,8 +5,10 @@ import ( "fmt" "github.com/fatih/color" + "github.com/scaleway/scaleway-cli/v2/internal/core" "github.com/scaleway/scaleway-cli/v2/internal/interactive" "github.com/scaleway/scaleway-cli/v2/internal/terminal" + "github.com/scaleway/scaleway-sdk-go/api/account/v2" "github.com/scaleway/scaleway-sdk-go/logger" "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/scaleway-sdk-go/validation" @@ -26,18 +28,40 @@ func promptOrganizationID(ctx context.Context) (string, error) { }) } -func promptProjectID(ctx context.Context) (string, error) { +func promptProjectID(ctx context.Context, accessKey string, secretKey string, organizationID string, defaultProjectID string) (string, error) { + client := core.ExtractClient(ctx) + api := account.NewAPI(client) + + res, err := api.ListProjects(&account.ListProjectsRequest{ + OrganizationID: organizationID, + }, scw.WithAllPages(), scw.WithContext(ctx), scw.WithAuthRequest(accessKey, secretKey)) + if err != nil { + return "", fmt.Errorf("failed to list projects: %w", err) + } + + defaultIndex := 0 + + projects := make([]string, len(res.Projects)) + for i := range res.Projects { + if res.Projects[i].ID == defaultProjectID { + defaultIndex = i + } + projects[i] = fmt.Sprintf("%s (%s)", res.Projects[i].Name, res.Projects[i].ID) + } + + prompt := interactive.ListPrompt{ + Prompt: "Choose your default project ID", + Choices: projects, + DefaultIndex: defaultIndex, + } + _, _ = interactive.Println() - return interactive.PromptStringWithConfig(&interactive.PromptStringConfig{ - Ctx: ctx, - Prompt: "Default project ID", - ValidateFunc: func(s string) error { - if !validation.IsUUID(s) { - return fmt.Errorf("given project ID is not a valid UUID") - } - return nil - }, - }) + index, err := prompt.Execute(ctx) + if err != nil { + return "", err + } + + return res.Projects[index].ID, nil } func promptTelemetry(ctx context.Context) (*bool, error) { diff --git a/internal/namespaces/init/testdata/test-init-prompt-simple.cassette.yaml b/internal/namespaces/init/testdata/test-init-prompt-simple.cassette.yaml new file mode 100644 index 0000000000..cc0cf778c6 --- /dev/null +++ b/internal/namespaces/init/testdata/test-init-prompt-simple.cassette.yaml @@ -0,0 +1,99 @@ +--- +version: 1 +interactions: +- request: + body: '{"access_key":"SCWQN1ZYHWPFGJD28Q70","secret_key":null,"description":"iam","created_at":"2022-08-22T09:13:42.922733Z","updated_at":"2022-10-20T08:29:52.752429Z","expires_at":null,"default_project_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","editable":true,"creation_ip":"51.159.73.9","user_id":"38d8ec28-dbee-4dbe-a4e8-56adcc285e8b"}' + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.20.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/iam/v1alpha1/api-keys/SCWXXXXXXXXXXXXXXXXX + method: GET + response: + body: '{"access_key":"SCWQN1ZYHWPFGJD28Q70","secret_key":null,"description":"iam","created_at":"2022-08-22T09:13:42.922733Z","updated_at":"2022-10-20T08:29:52.752429Z","expires_at":null,"default_project_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","editable":true,"creation_ip":"51.159.73.9","user_id":"38d8ec28-dbee-4dbe-a4e8-56adcc285e8b"}' + headers: + Content-Length: + - "332" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Tue, 30 May 2023 12:09:35 GMT + Server: + - Scaleway API-Gateway + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - c93bdf44-8a0f-487a-82bd-54ccb24951b3 + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"total_count":3,"projects":[{"id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","name":"default","organization_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","created_at":"2022-01-27T09:48:44.921507Z","updated_at":"2022-01-27T09:48:44.921507Z","description":""},{"id":"1fd9597f-1749-49b9-960d-52828d68573d","name":"test","organization_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","created_at":"2023-04-14T07:47:22.276196Z","updated_at":"2023-04-14T07:47:22.276196Z","description":""},{"id":"d34159dc-c4d8-4e64-a907-7bab424d2b08","name":"newproject","organization_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","created_at":"2023-05-30T09:42:48.468695Z","updated_at":"2023-05-30T09:42:48.468695Z","description":""}]}' + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.20.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/account/v2/projects?order_by=created_at_asc&organization_id=11111111-1111-1111-1111-111111111111&page=1 + method: GET + response: + body: '{"total_count":3,"projects":[{"id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","name":"default","organization_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","created_at":"2022-01-27T09:48:44.921507Z","updated_at":"2022-01-27T09:48:44.921507Z","description":""},{"id":"1fd9597f-1749-49b9-960d-52828d68573d","name":"test","organization_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","created_at":"2023-04-14T07:47:22.276196Z","updated_at":"2023-04-14T07:47:22.276196Z","description":""},{"id":"d34159dc-c4d8-4e64-a907-7bab424d2b08","name":"newproject","organization_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","created_at":"2023-05-30T09:42:48.468695Z","updated_at":"2023-05-30T09:42:48.468695Z","description":""}]}' + headers: + Content-Length: + - "699" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Tue, 30 May 2023 12:09:35 GMT + Server: + - Scaleway API-Gateway + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 84ae7d4b-c040-4a70-bd52-d5f3733b0688 + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"access_key":"SCWQN1ZYHWPFGJD28Q70","secret_key":null,"description":"iam","created_at":"2022-08-22T09:13:42.922733Z","updated_at":"2022-10-20T08:29:52.752429Z","expires_at":null,"default_project_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","editable":true,"creation_ip":"51.159.73.9","user_id":"38d8ec28-dbee-4dbe-a4e8-56adcc285e8b"}' + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.20.1; linux; amd64) scaleway-cli/0.0.0+test + url: https://api.scaleway.com/iam/v1alpha1/api-keys/SCWXXXXXXXXXXXXXXXXX + method: GET + response: + body: '{"access_key":"SCWQN1ZYHWPFGJD28Q70","secret_key":null,"description":"iam","created_at":"2022-08-22T09:13:42.922733Z","updated_at":"2022-10-20T08:29:52.752429Z","expires_at":null,"default_project_id":"ee7bd9e1-9cbd-4724-b2f4-19e50f3cf38b","editable":true,"creation_ip":"51.159.73.9","user_id":"38d8ec28-dbee-4dbe-a4e8-56adcc285e8b"}' + headers: + Content-Length: + - "332" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Tue, 30 May 2023 12:09:35 GMT + Server: + - Scaleway API-Gateway + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 71574abd-cede-4827-978c-a9320001de98 + status: 200 OK + code: 200 + duration: "" diff --git a/internal/namespaces/init/testdata/test-init-prompt-simple.golden b/internal/namespaces/init/testdata/test-init-prompt-simple.golden new file mode 100644 index 0000000000..d71726df02 --- /dev/null +++ b/internal/namespaces/init/testdata/test-init-prompt-simple.golden @@ -0,0 +1,9 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +βœ… Initialization completed with success. + Except for SSH key: could not find an SSH key at ~/.ssh/id_rsa.pub +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "message": "Initialization completed with success", + "details": "Except for SSH key: could not find an SSH key at ~/.ssh/id_rsa.pub" +}