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

Added Scaleway Shell Plugin #314

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
130 changes: 130 additions & 0 deletions plugins/scaleway/api_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package scaleway

import (
"context"
"os"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/importer"
"github.com/1Password/shell-plugins/sdk/provision"
"github.com/1Password/shell-plugins/sdk/schema"
"github.com/1Password/shell-plugins/sdk/schema/credname"
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
)

func APIKey() schema.CredentialType {
return schema.CredentialType{
Name: credname.APIKey,
DocsURL: sdk.URL("https://www.scaleway.com/en/docs/identity-and-access-management/iam/how-to/create-api-keys"),
ManagementURL: sdk.URL("https://console.scaleway.com/iam/api-keys"),
Fields: []schema.CredentialField{
{
Name: fieldname.AccessKeyID,
MarkdownDescription: "The ID of the API Key used to authenticate to Scaleway.",
Secret: false,
Composition: &schema.ValueComposition{
Length: 20,
Prefix: "SCW",
Charset: schema.Charset{
Uppercase: true,
Digits: true,
},
},
},
{
Name: fieldname.SecretAccessKey,
MarkdownDescription: "The secret access key used to authenticate to Scaleway.",
Secret: true,
Composition: &schema.ValueComposition{
Length: 36,
Charset: schema.Charset{
Lowercase: true,
Digits: true,
Specific: []rune{'-'},
},
},
},
{
Name: fieldname.DefaultOrganization,
MarkdownDescription: "The default organization ID to use for this access key.",
Secret: false,
Composition: &schema.ValueComposition{
Length: 36,
Charset: schema.Charset{
Lowercase: true,
Digits: true,
Specific: []rune{'-'},
},
},
},
{
Name: fieldname.DefaultRegion,
MarkdownDescription: "The default region to use for this access key.",
Optional: true,
},
{
Name: fieldname.DefaultZone,
MarkdownDescription: "The default zone to use for this access key.",
Optional: true,
},
},
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
Importer: importer.TryAll(
importer.TryEnvVarPair(defaultEnvVarMapping),
TryScalewayConfigFile(),
)}
}

var defaultEnvVarMapping = map[string]sdk.FieldName{
"SCW_ACCESS_KEY": fieldname.AccessKeyID,
"SCW_SECRET_KEY": fieldname.SecretAccessKey,
"SCW_DEFAULT_ORGANIZATION_ID": fieldname.DefaultOrganization,
"SCW_DEFAULT_REGION": fieldname.DefaultRegion,
"SCW_DEFAULT_ZONE": fieldname.DefaultZone,
arunsathiya marked this conversation as resolved.
Show resolved Hide resolved
}

func TryScalewayConfigFile() sdk.Importer {
file := os.Getenv("SCW_CONFIG_PATH")
if file == "" {
file = "~/.config/scw/config.yaml"
}
return importer.TryFile(file, func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) {
var config Config
if err := contents.ToYAML(&config); err != nil {
out.AddError(err)
return
}

for profileName, profile := range config.Profiles {
profileFields := make(map[sdk.FieldName]string)
profileFields[fieldname.AccessKeyID] = profile.AccessKey
profileFields[fieldname.SecretAccessKey] = profile.SecretKey
if profile.DefaultOrganizationID != "" {
profileFields[fieldname.DefaultOrganization] = profile.DefaultOrganizationID
}
if profile.DefaultRegion != "" {
profileFields[fieldname.DefaultRegion] = profile.DefaultRegion
}
if profile.DefaultZone != "" {
profileFields[fieldname.DefaultZone] = profile.DefaultZone
}

out.AddCandidate(sdk.ImportCandidate{
Fields: profileFields,
NameHint: importer.SanitizeNameHint(profileName),
})
}
})
}

type Config struct {
Profiles map[string]Profile `yaml:"profiles"`
}

type Profile struct {
AccessKey string `yaml:"access_key"`
SecretKey string `yaml:"secret_key"`
DefaultOrganizationID string `yaml:"default_organization_id"`
DefaultRegion string `yaml:"default_region"`
DefaultZone string `yaml:"default_zone"`
}
87 changes: 87 additions & 0 deletions plugins/scaleway/api_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package scaleway

import (
"testing"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/plugintest"
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
)

func TestAPIKeyImporter(t *testing.T) {
plugintest.TestImporter(t, APIKey().Importer, map[string]plugintest.ImportCase{
"Environment variables": {
Environment: map[string]string{
"SCW_ACCESS_KEY": "SCWSYXTFI97NSEXAMPLE",
"SCW_SECRET_KEY": "d9b67b48-873c-8ece-8270-e1e15example",
"SCW_DEFAULT_ORGANIZATION_ID": "11111111-2222-3333-4444-55555example",
arunsathiya marked this conversation as resolved.
Show resolved Hide resolved
"SCW_DEFAULT_REGION": "fr-par",
"SCW_DEFAULT_ZONE": "fr-par-1",
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: map[sdk.FieldName]string{
fieldname.AccessKeyID: "SCWSYXTFI97NSEXAMPLE",
fieldname.SecretAccessKey: "d9b67b48-873c-8ece-8270-e1e15example",
fieldname.DefaultOrganization: "11111111-2222-3333-4444-55555example",
fieldname.DefaultRegion: "fr-par",
fieldname.DefaultZone: "fr-par-1",
},
},
},
},
"SCW default config file location": {
Files: map[string]string{
"~/.config/scw/config.yaml": plugintest.LoadFixture(t, "simple.yaml"),
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: map[sdk.FieldName]string{
fieldname.AccessKeyID: "SCWSYXTFI97NSEXAMPLE",
fieldname.SecretAccessKey: "d9b67b48-873c-8ece-8270-e1e15example",
fieldname.DefaultOrganization: "11111111-2222-3333-4444-55555example",
},
},
},
},
"SCW config file with optional settings": {
Files: map[string]string{
"~/.config/scw/config.yaml": plugintest.LoadFixture(t, "optional.yaml"),
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: map[sdk.FieldName]string{
fieldname.AccessKeyID: "SCWSYXTFI97NSEXAMPLE",
fieldname.SecretAccessKey: "d9b67b48-873c-8ece-8270-e1e15example",
fieldname.DefaultOrganization: "11111111-2222-3333-4444-55555example",
fieldname.DefaultRegion: "fr-par",
fieldname.DefaultZone: "fr-par-1",
},
},
},
},
})
}

func TestAPIKeyProvisioner(t *testing.T) {
plugintest.TestProvisioner(t, APIKey().DefaultProvisioner, map[string]plugintest.ProvisionCase{
"default": {
ItemFields: map[sdk.FieldName]string{
fieldname.AccessKeyID: "SCWSYXTFI97NSEXAMPLE",
fieldname.SecretAccessKey: "d9b67b48-873c-8ece-8270-e1e15example",
fieldname.DefaultOrganization: "11111111-2222-3333-4444-55555example",
arunsathiya marked this conversation as resolved.
Show resolved Hide resolved
fieldname.DefaultRegion: "fr-par",
fieldname.DefaultZone: "fr-par-1",
},
ExpectedOutput: sdk.ProvisionOutput{
Environment: map[string]string{
"SCW_ACCESS_KEY": "SCWSYXTFI97NSEXAMPLE",
"SCW_SECRET_KEY": "d9b67b48-873c-8ece-8270-e1e15example",
"SCW_DEFAULT_ORGANIZATION_ID": "11111111-2222-3333-4444-55555example",
"SCW_DEFAULT_REGION": "fr-par",
"SCW_DEFAULT_ZONE": "fr-par-1",
},
},
},
})
}
22 changes: 22 additions & 0 deletions plugins/scaleway/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package scaleway

import (
"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/schema"
)

func New() schema.Plugin {
return schema.Plugin{
Name: "scaleway",
Platform: schema.PlatformInfo{
Name: "Scaleway",
Homepage: sdk.URL("https://scaleway.com"),
},
Credentials: []schema.CredentialType{
APIKey(),
},
Executables: []schema.Executable{
ScalewayCLI(),
},
}
}
27 changes: 27 additions & 0 deletions plugins/scaleway/scw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package scaleway

import (
"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/needsauth"
"github.com/1Password/shell-plugins/sdk/schema"
"github.com/1Password/shell-plugins/sdk/schema/credname"
)

func ScalewayCLI() schema.Executable {
return schema.Executable{
Name: "Scaleway CLI",
Runs: []string{"scw"},
DocsURL: sdk.URL("https://www.scaleway.com/en/cli"),
NeedsAuth: needsauth.IfAll(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's skip for -p as well, because that applies only when the configuration file exists on the computer. So, it's not relevant when a shell plugin is being used.

needsauth.NotForHelpOrVersion(),
needsauth.NotWithoutArgs(),
needsauth.NotWhenContainsArgs("-c"),
needsauth.NotWhenContainsArgs("--config"),
),
Uses: []schema.CredentialUsage{
{
Name: credname.APIKey,
},
},
}
}
6 changes: 6 additions & 0 deletions plugins/scaleway/test-fixtures/optional.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
access_key: SCWSYXTFI97NSEXAMPLE
secret_key: d9b67b48-873c-8ece-8270-e1e15example
default_organization_id: 11111111-2222-3333-4444-55555example
default_region: fr-par
default_zone: fr-par-1
3 changes: 3 additions & 0 deletions plugins/scaleway/test-fixtures/simple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
access_key: SCWSYXTFI97NSEXAMPLE
secret_key: d9b67b48-873c-8ece-8270-e1e15example
default_organization_id: 11111111-2222-3333-4444-55555example
Loading