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: add SSH-Key support in init #760

Merged
merged 38 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9f8373a
feat: add SSH-Key support in init
loicbourgois Mar 10, 2020
0cc425b
add golden
loicbourgois Mar 10, 2020
ad9c1be
fix
loicbourgois Mar 10, 2020
a467040
update golden
loicbourgois Mar 10, 2020
116b06a
wip
loicbourgois Mar 10, 2020
5a58e61
fix
loicbourgois Mar 10, 2020
241ed84
fix
loicbourgois Mar 10, 2020
690c9af
fix
loicbourgois Mar 10, 2020
8b1d5dc
fix
loicbourgois Mar 11, 2020
328f8b1
fix
loicbourgois Mar 11, 2020
1b4e45c
address comment
loicbourgois Mar 13, 2020
f89c2fe
address comment
loicbourgois Mar 13, 2020
2ebb3b3
update golden
loicbourgois Mar 13, 2020
cfc4359
remove useless golden
loicbourgois Mar 13, 2020
6415de5
add ExtractClientOrCreate()
scaleway-bot Mar 16, 2020
0279e4c
fix
loicbourgois Mar 16, 2020
9200f66
wip: add test
loicbourgois Mar 20, 2020
cfb11c3
wip
loicbourgois Mar 20, 2020
a9ebef4
wip
loicbourgois Mar 20, 2020
eb0ebbf
update goldens
loicbourgois Mar 20, 2020
8366463
wip: test
loicbourgois Mar 20, 2020
3881ebe
wip: test
loicbourgois Mar 20, 2020
91baa6c
wip: test
loicbourgois Mar 20, 2020
3eb57e1
wip: test
loicbourgois Mar 20, 2020
34a19fc
wip: test
loicbourgois Mar 20, 2020
e2948cf
wip: test
loicbourgois Mar 20, 2020
54b95c4
wip: test 2
loicbourgois Mar 20, 2020
052ba26
wip: test 3
loicbourgois Mar 20, 2020
8fb7a86
wip: test 4
loicbourgois Mar 20, 2020
f20cb29
wip: test bug
loicbourgois Mar 20, 2020
ffb0ea4
wip: test
loicbourgois Mar 23, 2020
7f753d2
wip: test
loicbourgois Mar 23, 2020
21520bf
wip: test
loicbourgois Mar 23, 2020
e2c6a88
wip: update rights
loicbourgois Mar 23, 2020
ca7d8ec
test
loicbourgois Mar 24, 2020
e7b2ca6
cleanup
loicbourgois Mar 24, 2020
f3a73c6
address comments
loicbourgois Mar 26, 2020
2777380
fix
loicbourgois Mar 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Initiliaze SSH key.

USAGE:
scw account ssh-key init

FLAGS:
-h, --help help for init

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Manage SSH key.

USAGE:
scw account ssh-key <command>

AVAILABLE COMMANDS:
init Initiliaze SSH key

FLAGS:
-h, --help help for ssh-key

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use

Use "scw account ssh-key [command] --help" for more information about a command.
1 change: 1 addition & 0 deletions cmd/scw/testdata/test-main-usage-usage.stderr.golden
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ AVAILABLE COMMANDS:
marketplace Marketplace API
init Initialize the config
config Config file management
account Manage SSH key
autocomplete Install autocompletion script
version Display cli version
help Help about any command
Expand Down
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1p
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/certifi/gocertifi v0.0.0-20200104152315-a6d78f326758 h1:epkmRmrjzR0Km6DrVMk/ZQwDdMY2w31I3kQT91DbxS0=
github.com/certifi/gocertifi v0.0.0-20200104152315-a6d78f326758/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
Expand All @@ -35,9 +37,12 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
Expand All @@ -53,14 +58,6 @@ 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.5.0.20200226081452-7bdc7806b035 h1:PGuOvUWTkkNFh/cN4IIR45YaFWfbLgijvarr7mBqUFg=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200226081452-7bdc7806b035/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200316165553-4378e6801116 h1:vHShZ6sgpWTTN9xnrBMOwyjVbA8D7xcGOGyCfgkXJTU=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200316165553-4378e6801116/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200317080505-8dd22a160c48 h1:LX+2i/gWH+X013HCisZ3/dB8cF6h2wdn60iemwe92D4=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200317080505-8dd22a160c48/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200317142453-2a0af47d63be h1:FX+wAaLvpWFqgQIROo0f2iTefe+phJWFUBuEG2HPDW8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200317142453-2a0af47d63be/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200319151040-8db41486782b h1:MHFYWCAxh6gqGEzdht6Zx8r917FDXyNDo5mhN40Q9X4=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200319151040-8db41486782b/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200324130151-e0b5fd35d2c8 h1:/dunZoNLCRQF6DCpSiyK7vXPsR7aWTJVICUXxkakGc8=
Expand Down Expand Up @@ -95,6 +92,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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=
Expand Down
8 changes: 6 additions & 2 deletions internal/core/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func createClient(meta *meta) (*scw.Client, error) {
return nil, err
}

if meta.ProfileFlag != "" {
if meta != nil && meta.ProfileFlag != "" {
config.ActiveProfile = scw.StringPtr(meta.ProfileFlag)
}

Expand Down Expand Up @@ -53,8 +53,12 @@ func createClient(meta *meta) (*scw.Client, error) {
}
}

userAgent := "scaleway-cli/"
if meta != nil {
userAgent += meta.BuildInfo.Version.String()
}
opts := []scw.ClientOption{
scw.WithUserAgent("scaleway-cli/" + meta.BuildInfo.Version.String()),
scw.WithUserAgent(userAgent),
scw.WithProfile(profile),
}

Expand Down
12 changes: 12 additions & 0 deletions internal/core/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ func ExtractClient(ctx context.Context) *scw.Client {
return extractMeta(ctx).Client
}

func ExtractClientOrCreate(ctx context.Context) (*scw.Client, error) {
client := ExtractClient(ctx)
if client == nil {
var err error
client, err = createClient(nil)
if err != nil {
return nil, err
}
}
return client, nil
}

func ExtractBuildInfo(ctx context.Context) *BuildInfo {
return extractMeta(ctx).BuildInfo
}
Expand Down
121 changes: 121 additions & 0 deletions internal/namespaces/account/custom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package account

import (
"context"
"io/ioutil"
"os"
"path"
"reflect"
"strings"

"github.com/scaleway/scaleway-cli/internal/args"
"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-cli/internal/interactive"
account "github.com/scaleway/scaleway-sdk-go/api/account/v2alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

func GetCommands() *core.Commands {
return core.NewCommands(
sshKeyCommand(),
initCommand(),
)
}

func sshKeyCommand() *core.Command {
return &core.Command{
Short: `Manage SSH key`,
Long: `Manage SSH key.`,
Namespace: "account",
Resource: "ssh-key",
NoClient: true,
ArgsType: reflect.TypeOf(args.RawArgs{}),
}
}

func initCommand() *core.Command {
return &core.Command{
Short: `Initiliaze SSH key`,
Long: `Initiliaze SSH key.`,
Namespace: "account",
Resource: "ssh-key",
Verb: "init",
ArgsType: reflect.TypeOf(args.RawArgs{}),
ArgSpecs: core.ArgSpecs{},
Run: initRunWrapper,
}
}

func initRunWrapper(ctx context.Context, argsI interface{}) (i interface{}, e error) {
return InitRunInner(ctx, nil)
}

func InitRunInner(ctx context.Context, withSSHKey *bool) (i interface{}, e error) {
// Explanation
_, _ = interactive.Println("An SSH key is required if you want to connect to a server. More info at https://www.scaleway.com/en/docs/configure-new-ssh-key/")

// Get default SSH key locally
relativePath := path.Join(".ssh", "id_rsa.pub")
filename := path.Join(core.ExtractEnv(ctx, "HOME"), relativePath)
shortenedFilename := "~/" + relativePath
localSSHKeyContent, err := ioutil.ReadFile(filename)

addKeyInstructions := `scw account ssh-key add name=my-key key="$(cat path/to/my/key.pub)"`

// Early exit if key is not present locally
if os.IsNotExist(err) {
return nil, sshKeyNotFound(filename, addKeyInstructions)
} else if err != nil {
return nil, err
}

// Get all SSH keys from Scaleway
client, err := core.ExtractClientOrCreate(ctx)
if err != nil {
return nil, err
}

api := account.NewAPI(client)
listSSHKeysResponse, err := api.ListSSHKeys(&account.ListSSHKeysRequest{}, scw.WithAllPages())
if err != nil {
return nil, err
}

// Early exit if the SSH key is present locally and on Scaleway
for _, SSHKey := range listSSHKeysResponse.SSHKeys {
if strings.TrimSpace(SSHKey.PublicKey) == strings.TrimSpace(string(localSSHKeyContent)) {
return nil, sshKeyAlreadyPresent(shortenedFilename)
}
}

// Ask user
addSSHKey := false
if withSSHKey != nil {
addSSHKey = *withSSHKey
} else {
addSSHKey, err = interactive.PromptBoolWithConfig(&interactive.PromptBoolConfig{
Prompt: "We found an SSH key in " + shortenedFilename + ". Do you want to add it to your Scaleway account ?",
DefaultValue: true,
})
if err != nil {
return nil, err
}
}

// Early exit if user doesn't want to add the key
if !addSSHKey {
return nil, installationCanceled(addKeyInstructions)
}

// Add key
_, err = api.CreateSSHKey(&account.CreateSSHKeyRequest{
PublicKey: string(localSSHKeyContent),
})
if err != nil {
return nil, err
}

return core.SuccessResult{
Message: "Key " + shortenedFilename + " successfully added",
}, nil
}
39 changes: 39 additions & 0 deletions internal/namespaces/account/custom_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package account

import (
"io/ioutil"
"os"
"path"
"testing"

"github.com/scaleway/scaleway-cli/internal/core"
)

func Test_initCommand(t *testing.T) {
t.Run("simple", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: func(ctx *core.BeforeFuncCtx) error {
tmpDir := os.TempDir()
pathToPublicKey := path.Join(tmpDir, ".ssh", "id_rsa.pub")
_, err := os.Stat(pathToPublicKey)
if err != nil {
content := "ssh-rsa AAAAB3NzaC1yc2EAAAEDAQABAAABAQC/wF8Q8LjEexuWDc8TfKmWVZ1CiiHK6KvO0E/Rk9+d6ssqbrvtbJWRsJXZFC8+DGWVM0UFFicmOfTwEjDWzuQPFkYhmpXrD1UiLx9Viku1g1qEJgcsyH2uAwwW3OnsH1W44D6Ni/zOzMButFeKZgPeD8H9YNkpbZBZ9QrKFiAhvEyJDYSY0bsbH1/qR5DE+dLNuGlJ/g3kUMVaXSI6dHNcBHTbK0Mse23Uopk2U3BSpvX9JdbcLaYtHDOytwd16rNYui7el3uOmlR8oUpAXkeKQxBPoxgy3qI/P8/l44L9RFpbklkmdiw2ph2ymiSkRSYCWdvEVIK/A+0D8VFjGXOb email"
err := os.MkdirAll(path.Join(tmpDir, ".ssh"), 0755)
if err != nil {
return err
}
err = ioutil.WriteFile(pathToPublicKey, []byte(content), 0644)
return err
}
return err
},
Cmd: `scw account ssh-key init with-ssh-key=true`,
Check: core.TestCheckCombine(
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
OverrideEnv: map[string]string{
"HOME": os.TempDir(),
},
}))
}
27 changes: 27 additions & 0 deletions internal/namespaces/account/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package account

import (
"fmt"

"github.com/scaleway/scaleway-cli/internal/core"
)

func installationCanceled(addKeyInstructions string) *core.CliError {
return &core.CliError{
Err: fmt.Errorf("installation of SSH key canceled"),
Hint: "Add it later using " + addKeyInstructions,
}
}

func sshKeyNotFound(filename string, addKeyInstructions string) *core.CliError {
return &core.CliError{
Err: fmt.Errorf("could not find an ssh key at " + filename),
Hint: "Add one later using " + addKeyInstructions,
}
}

func sshKeyAlreadyPresent(shortenedFilename string) *core.CliError {
return &core.CliError{
Err: fmt.Errorf("key " + shortenedFilename + " is already present on your scaleway account"),
}
}
Loading