From b81b9599f6ba2e2d3296cab5ca1bf2180a2e7266 Mon Sep 17 00:00:00 2001 From: "J-K. Solbakken" Date: Wed, 9 Apr 2025 08:57:28 +0200 Subject: [PATCH 1/5] Working plugin for the Scaleway CLI, no support for profiles yet --- plugins/scaleway/access_key.go | 147 ++++++++++++++++++++++++++ plugins/scaleway/access_key_test.go | 78 ++++++++++++++ plugins/scaleway/plugin.go | 22 ++++ plugins/scaleway/scw.go | 25 +++++ plugins/scaleway/test-fixtures/config | 7 ++ sdk/schema/fieldname/names.go | 1 + 6 files changed, 280 insertions(+) create mode 100644 plugins/scaleway/access_key.go create mode 100644 plugins/scaleway/access_key_test.go create mode 100644 plugins/scaleway/plugin.go create mode 100644 plugins/scaleway/scw.go create mode 100644 plugins/scaleway/test-fixtures/config diff --git a/plugins/scaleway/access_key.go b/plugins/scaleway/access_key.go new file mode 100644 index 000000000..902f3bdf2 --- /dev/null +++ b/plugins/scaleway/access_key.go @@ -0,0 +1,147 @@ +package scaleway + +import ( + "context" + + "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 AccessKey() schema.CredentialType { + return schema.CredentialType{ + Name: credname.AccessKey, + DocsURL: sdk.URL("https://www.scaleway.com/en/docs/iam/how-to/create-api-keys/"), + ManagementURL: sdk.URL("https://console.scaleway.com/iam/api-keys"), + Fields: []schema.CredentialField{ + { + Name: fieldname.AccessKeyID, + MarkdownDescription: "Access key", + Secret: false, + Optional: false, + Composition: &schema.ValueComposition{ + Length: 20, + Charset: schema.Charset{ + Uppercase: true, + Digits: true, + }, + }, + }, + { + Name: fieldname.SecretAccessKey, + MarkdownDescription: "Secret key.", + Secret: true, + Optional: false, + Composition: &schema.ValueComposition{ + Length: 36, + Charset: schema.Charset{ + Lowercase: true, + Digits: true, + }, + }, + }, + { + Name: fieldname.DefaultRegion, + MarkdownDescription: "Default region.", + Secret: false, + Optional: true, + Composition: &schema.ValueComposition{ + Charset: schema.Charset{ + Lowercase: true, + Uppercase: true, + Digits: true, + }, + }, + }, + { + Name: fieldname.DefaultZone, + MarkdownDescription: "Default zone.", + Secret: false, + Optional: true, + Composition: &schema.ValueComposition{ + Charset: schema.Charset{ + Lowercase: true, + Uppercase: true, + Digits: true, + }, + }, + }, + { + Name: fieldname.ProjectID, + MarkdownDescription: "Project ID.", + Secret: false, + Optional: true, + Composition: &schema.ValueComposition{ + Charset: schema.Charset{ + Lowercase: true, + Uppercase: true, + Digits: true, + }, + }, + }, + { + Name: fieldname.OrgID, + MarkdownDescription: "Organization ID.", + Secret: false, + Optional: true, + Composition: &schema.ValueComposition{ + Charset: schema.Charset{ + Lowercase: true, + Uppercase: true, + Digits: 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_REGION": fieldname.DefaultRegion, + "SCW_DEFAULT_ZONE": fieldname.DefaultZone, + "SCW_PROJECT_ID": fieldname.ProjectID, + "SCW_DEFAULT_ORGANIZATION_ID": fieldname.OrgID, +} + +func TryScalewayConfigFile() sdk.Importer { + return importer.TryFile("~/.config/scw/config.yaml", 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 + } + + if config.AccessKey == "" || config.SecretKey == "" { + return + } + + out.AddCandidate(sdk.ImportCandidate{ + Fields: map[sdk.FieldName]string{ + fieldname.AccessKeyID: config.AccessKey, + fieldname.SecretAccessKey: config.SecretKey, + fieldname.DefaultRegion: config.DefaultRegion, + fieldname.DefaultZone: config.DefaultZone, + fieldname.ProjectID: config.ProjectID, + fieldname.OrgID: config.OrganizationID, + }, + }) + }) +} + +type Config struct { + AccessKey string `yaml:"access_key"` + SecretKey string `yaml:"secret_key"` + DefaultRegion string `yaml:"default_region,omitempty"` + DefaultZone string `yaml:"default_zone,omitempty"` + ProjectID string `yaml:"default_project_id,omitempty"` + OrganizationID string `yaml:"default_organization_id,omitempty"` +} diff --git a/plugins/scaleway/access_key_test.go b/plugins/scaleway/access_key_test.go new file mode 100644 index 000000000..6aadb14f0 --- /dev/null +++ b/plugins/scaleway/access_key_test.go @@ -0,0 +1,78 @@ +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 TestAccessKeyProvisioner(t *testing.T) { + plugintest.TestProvisioner(t, AccessKey().DefaultProvisioner, map[string]plugintest.ProvisionCase{ + "default": { + ItemFields: map[sdk.FieldName]string{ + fieldname.AccessKeyID: "AABBCCDDEEFFGGHHIIJJ", + fieldname.SecretAccessKey: "c3a22663-2770-4428-8166-c214643cd70b", + fieldname.DefaultRegion: "fr-par", + fieldname.DefaultZone: "fr-par-1", + fieldname.ProjectID: "d3a22663-2770-4428-8166-c214643cd70c", + fieldname.OrgID: "e3a22663-2770-4428-8166-c214643cd70d", + }, + ExpectedOutput: sdk.ProvisionOutput{ + Environment: map[string]string{ + "SCW_ACCESS_KEY": "AABBCCDDEEFFGGHHIIJJ", + "SCW_SECRET_KEY": "c3a22663-2770-4428-8166-c214643cd70b", + "SCW_DEFAULT_REGION": "fr-par", + "SCW_DEFAULT_ZONE": "fr-par-1", + "SCW_PROJECT_ID": "d3a22663-2770-4428-8166-c214643cd70c", + "SCW_DEFAULT_ORGANIZATION_ID": "e3a22663-2770-4428-8166-c214643cd70d", + }, + }, + }, + }) +} + +func TestAccessKeyImporter(t *testing.T) { + plugintest.TestImporter(t, AccessKey().Importer, map[string]plugintest.ImportCase{ + "environment": { + Environment: map[string]string{ + "SCW_ACCESS_KEY": "yolo", + "SCW_SECRET_KEY": "c3a22663-2770-4428-8166-c214643cd70b", + "SCW_DEFAULT_REGION": "fr-par", + "SCW_DEFAULT_ZONE": "fr-par-1", + "SCW_PROJECT_ID": "01696acf-7a78-4d94-a129-5e135d0377cc", + "SCW_DEFAULT_ORGANIZATION_ID": "14800390-5df1-4a90-b38e-9b461bdcd108", + }, + ExpectedCandidates: []sdk.ImportCandidate{ + { + Fields: map[sdk.FieldName]string{ + fieldname.AccessKeyID: "yolo", + fieldname.SecretAccessKey: "c3a22663-2770-4428-8166-c214643cd70b", + fieldname.DefaultRegion: "fr-par", + fieldname.DefaultZone: "fr-par-1", + fieldname.ProjectID: "01696acf-7a78-4d94-a129-5e135d0377cc", + fieldname.OrgID: "14800390-5df1-4a90-b38e-9b461bdcd108", + }, + }, + }, + }, + "config file": { + Files: map[string]string{ + "~/.config/scw/config.yaml": plugintest.LoadFixture(t, "config"), + }, + ExpectedCandidates: []sdk.ImportCandidate{ + { + Fields: map[sdk.FieldName]string{ + fieldname.AccessKeyID: "yolo", + fieldname.SecretAccessKey: "c3a22663-2770-4428-8166-c214643cd70b", + fieldname.DefaultRegion: "fr-par", + fieldname.DefaultZone: "fr-par-1", + fieldname.ProjectID: "01696acf-7a78-4d94-a129-5e135d0377cc", + fieldname.OrgID: "14800390-5df1-4a90-b38e-9b461bdcd108", + }, + }, + }, + }, + }) +} diff --git a/plugins/scaleway/plugin.go b/plugins/scaleway/plugin.go new file mode 100644 index 000000000..180fc4e95 --- /dev/null +++ b/plugins/scaleway/plugin.go @@ -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{ + AccessKey(), + }, + Executables: []schema.Executable{ + ScalewayCLI(), + }, + } +} diff --git a/plugins/scaleway/scw.go b/plugins/scaleway/scw.go new file mode 100644 index 000000000..a6bea5efc --- /dev/null +++ b/plugins/scaleway/scw.go @@ -0,0 +1,25 @@ +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( + needsauth.NotForHelpOrVersion(), + needsauth.NotWithoutArgs(), + ), + Uses: []schema.CredentialUsage{ + { + Name: credname.AccessKey, + }, + }, + } +} diff --git a/plugins/scaleway/test-fixtures/config b/plugins/scaleway/test-fixtures/config new file mode 100644 index 000000000..fe3b64176 --- /dev/null +++ b/plugins/scaleway/test-fixtures/config @@ -0,0 +1,7 @@ +# comment +access_key: yolo +secret_key: c3a22663-2770-4428-8166-c214643cd70b +default_organization_id: 14800390-5df1-4a90-b38e-9b461bdcd108 +default_project_id: 01696acf-7a78-4d94-a129-5e135d0377cc +default_region: fr-par +default_zone: fr-par-1 diff --git a/sdk/schema/fieldname/names.go b/sdk/schema/fieldname/names.go index 08cfa4e05..1ffc34a6d 100644 --- a/sdk/schema/fieldname/names.go +++ b/sdk/schema/fieldname/names.go @@ -28,6 +28,7 @@ const ( Credentials = sdk.FieldName("Credentials") Database = sdk.FieldName("Database") DefaultRegion = sdk.FieldName("Default Region") + DefaultZone = sdk.FieldName("Default Zone") Deployment = sdk.FieldName("Deployment") Email = sdk.FieldName("Email") Endpoint = sdk.FieldName("Endpoint") From 6a10050f1a8666a3febde228cc61a031135b21d1 Mon Sep 17 00:00:00 2001 From: "J-K. Solbakken" Date: Thu, 10 Apr 2025 19:20:40 +0200 Subject: [PATCH 2/5] gofmt-ed --- plugins/scaleway/scw.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/scaleway/scw.go b/plugins/scaleway/scw.go index a6bea5efc..ee75b2c2e 100644 --- a/plugins/scaleway/scw.go +++ b/plugins/scaleway/scw.go @@ -9,9 +9,9 @@ import ( func ScalewayCLI() schema.Executable { return schema.Executable{ - Name: "Scaleway CLI", - Runs: []string{"scw"}, - DocsURL: sdk.URL("https://www.scaleway.com/en/cli/"), + Name: "Scaleway CLI", + Runs: []string{"scw"}, + DocsURL: sdk.URL("https://www.scaleway.com/en/cli/"), NeedsAuth: needsauth.IfAll( needsauth.NotForHelpOrVersion(), needsauth.NotWithoutArgs(), From 5381ba44d6848895e7c15a05c1ac026055bbf2bc Mon Sep 17 00:00:00 2001 From: "J-K. Solbakken" Date: Tue, 15 Apr 2025 20:44:48 +0200 Subject: [PATCH 3/5] corrected env var name --- plugins/scaleway/access_key.go | 2 +- plugins/scaleway/access_key_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/scaleway/access_key.go b/plugins/scaleway/access_key.go index 902f3bdf2..bf615b277 100644 --- a/plugins/scaleway/access_key.go +++ b/plugins/scaleway/access_key.go @@ -108,7 +108,7 @@ var defaultEnvVarMapping = map[string]sdk.FieldName{ "SCW_SECRET_KEY": fieldname.SecretAccessKey, "SCW_DEFAULT_REGION": fieldname.DefaultRegion, "SCW_DEFAULT_ZONE": fieldname.DefaultZone, - "SCW_PROJECT_ID": fieldname.ProjectID, + "SCW_DEFAULT_PROJECT_ID": fieldname.ProjectID, "SCW_DEFAULT_ORGANIZATION_ID": fieldname.OrgID, } diff --git a/plugins/scaleway/access_key_test.go b/plugins/scaleway/access_key_test.go index 6aadb14f0..cb7e11352 100644 --- a/plugins/scaleway/access_key_test.go +++ b/plugins/scaleway/access_key_test.go @@ -25,7 +25,7 @@ func TestAccessKeyProvisioner(t *testing.T) { "SCW_SECRET_KEY": "c3a22663-2770-4428-8166-c214643cd70b", "SCW_DEFAULT_REGION": "fr-par", "SCW_DEFAULT_ZONE": "fr-par-1", - "SCW_PROJECT_ID": "d3a22663-2770-4428-8166-c214643cd70c", + "SCW_DEFAULT_PROJECT_ID": "d3a22663-2770-4428-8166-c214643cd70c", "SCW_DEFAULT_ORGANIZATION_ID": "e3a22663-2770-4428-8166-c214643cd70d", }, }, @@ -41,7 +41,7 @@ func TestAccessKeyImporter(t *testing.T) { "SCW_SECRET_KEY": "c3a22663-2770-4428-8166-c214643cd70b", "SCW_DEFAULT_REGION": "fr-par", "SCW_DEFAULT_ZONE": "fr-par-1", - "SCW_PROJECT_ID": "01696acf-7a78-4d94-a129-5e135d0377cc", + "SCW_DEFAULT_PROJECT_ID": "01696acf-7a78-4d94-a129-5e135d0377cc", "SCW_DEFAULT_ORGANIZATION_ID": "14800390-5df1-4a90-b38e-9b461bdcd108", }, ExpectedCandidates: []sdk.ImportCandidate{ From f268bdc52bc5417f4e82f651467323b2a352e3ba Mon Sep 17 00:00:00 2001 From: "J-K. Solbakken" Date: Tue, 15 Apr 2025 21:12:46 +0200 Subject: [PATCH 4/5] gofmt --- plugins/scaleway/access_key.go | 2 +- plugins/scaleway/access_key_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaleway/access_key.go b/plugins/scaleway/access_key.go index bf615b277..09e786988 100644 --- a/plugins/scaleway/access_key.go +++ b/plugins/scaleway/access_key.go @@ -108,7 +108,7 @@ var defaultEnvVarMapping = map[string]sdk.FieldName{ "SCW_SECRET_KEY": fieldname.SecretAccessKey, "SCW_DEFAULT_REGION": fieldname.DefaultRegion, "SCW_DEFAULT_ZONE": fieldname.DefaultZone, - "SCW_DEFAULT_PROJECT_ID": fieldname.ProjectID, + "SCW_DEFAULT_PROJECT_ID": fieldname.ProjectID, "SCW_DEFAULT_ORGANIZATION_ID": fieldname.OrgID, } diff --git a/plugins/scaleway/access_key_test.go b/plugins/scaleway/access_key_test.go index cb7e11352..a6ec74a0f 100644 --- a/plugins/scaleway/access_key_test.go +++ b/plugins/scaleway/access_key_test.go @@ -25,7 +25,7 @@ func TestAccessKeyProvisioner(t *testing.T) { "SCW_SECRET_KEY": "c3a22663-2770-4428-8166-c214643cd70b", "SCW_DEFAULT_REGION": "fr-par", "SCW_DEFAULT_ZONE": "fr-par-1", - "SCW_DEFAULT_PROJECT_ID": "d3a22663-2770-4428-8166-c214643cd70c", + "SCW_DEFAULT_PROJECT_ID": "d3a22663-2770-4428-8166-c214643cd70c", "SCW_DEFAULT_ORGANIZATION_ID": "e3a22663-2770-4428-8166-c214643cd70d", }, }, From 7b08bdd9f716ff172e16e0dfa6f0a3bff5c91492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-K=C3=A5re=20Solbakken?= Date: Tue, 20 May 2025 17:30:53 +0200 Subject: [PATCH 5/5] Update plugins/scaleway/access_key.go Co-authored-by: Simon Barendse <9931648+SimonBarendse@users.noreply.github.com> --- plugins/scaleway/access_key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaleway/access_key.go b/plugins/scaleway/access_key.go index 09e786988..6f7f2b5ce 100644 --- a/plugins/scaleway/access_key.go +++ b/plugins/scaleway/access_key.go @@ -19,7 +19,7 @@ func AccessKey() schema.CredentialType { Fields: []schema.CredentialField{ { Name: fieldname.AccessKeyID, - MarkdownDescription: "Access key", + MarkdownDescription: "Access key ID", Secret: false, Optional: false, Composition: &schema.ValueComposition{