From 12392c268da3d0a83fdbed4d25e22ee6e9173d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Wed, 1 Jul 2020 14:28:05 +0200 Subject: [PATCH 1/5] instance: add support for cloud-init --- .../namespaces/instance/v1/custom_server_create.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/namespaces/instance/v1/custom_server_create.go b/internal/namespaces/instance/v1/custom_server_create.go index 3c9ff633ba..9d49f71da5 100644 --- a/internal/namespaces/instance/v1/custom_server_create.go +++ b/internal/namespaces/instance/v1/custom_server_create.go @@ -33,6 +33,7 @@ type instanceCreateServerRequest struct { SecurityGroupID string PlacementGroupID string BootscriptID string + CloudInit string } // TODO: Remove all error uppercase and punctuations when [APIGW-1367] will be done @@ -99,6 +100,10 @@ func serverCreateCommand() *core.Command { Name: "bootscript-id", Short: "The bootscript ID to use, if empty the local boot will be used", }, + { + Name: "cloud-init", + Short: "The cloud-init script to use", + }, core.OrganizationIDArgSpec(), core.ZoneArgSpec(), }, @@ -313,6 +318,13 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac serverReq.PlacementGroup = scw.StringPtr(args.PlacementGroupID) } + // + // Cloud-init + // + if args.CloudInit != "" { + serverReq.Cloud = scw.StringPtr(args.CloudInit) + } + // // STEP 2: Resource creations and modifications. // From b889519c6acbe9409d967943f0b2feff482e4a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Wed, 1 Jul 2020 14:54:22 +0200 Subject: [PATCH 2/5] Fix --- .../instance/v1/custom_server_create.go | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/internal/namespaces/instance/v1/custom_server_create.go b/internal/namespaces/instance/v1/custom_server_create.go index 9d49f71da5..9e9aa0ad03 100644 --- a/internal/namespaces/instance/v1/custom_server_create.go +++ b/internal/namespaces/instance/v1/custom_server_create.go @@ -1,8 +1,10 @@ package instance import ( + "bytes" "context" "fmt" + "io" "net" "reflect" "strconv" @@ -318,13 +320,6 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac serverReq.PlacementGroup = scw.StringPtr(args.PlacementGroupID) } - // - // Cloud-init - // - if args.CloudInit != "" { - serverReq.Cloud = scw.StringPtr(args.CloudInit) - } - // // STEP 2: Resource creations and modifications. // @@ -346,7 +341,7 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac } // - // Server + // Server Creation // logger.Debugf("creating server") serverRes, err := apiInstance.CreateServer(serverReq) @@ -368,6 +363,22 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac server := serverRes.Server logger.Debugf("server created %s", server.ID) + // + // Cloud-init + // + if args.CloudInit != "" { + userData := make(map[string]io.Reader, len(args.CloudInit)) + userData["cloud-init"] = bytes.NewBufferString(args.CloudInit) + err := apiInstance.SetAllServerUserData(&instance.SetAllServerUserDataRequest{ + Zone: args.Zone, + ServerID: server.ID, + UserData: userData, + }) + if err != nil { + return nil, fmt.Errorf("error while setting up your cloud-init metadata: %s", err) + } + } + // // Start server by default // From 0d42a3638545e96f76a7633146c7157408395771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Wed, 1 Jul 2020 14:59:20 +0200 Subject: [PATCH 3/5] Fix --- .../testdata/test-all-usage-instance-server-create-usage.golden | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/scw/testdata/test-all-usage-instance-server-create-usage.golden b/cmd/scw/testdata/test-all-usage-instance-server-create-usage.golden index c27ba61fd1..c50ff53ba8 100644 --- a/cmd/scw/testdata/test-all-usage-instance-server-create-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-server-create-usage.golden @@ -35,6 +35,7 @@ ARGS: [security-group-id] The security group ID it use for this server [placement-group-id] The placement group ID in witch the server has to be created [bootscript-id] The bootscript ID to use, if empty the local boot will be used + [cloud-init] The cloud-init script to use [organization-id] Organization ID to use. If none is passed will use default organization ID from the config [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config From c97056e70158f005d6723e70e257748d2b90fee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Wed, 1 Jul 2020 15:14:38 +0200 Subject: [PATCH 4/5] Fix --- .../namespaces/instance/v1/custom_server_create.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/namespaces/instance/v1/custom_server_create.go b/internal/namespaces/instance/v1/custom_server_create.go index 9e9aa0ad03..720744da77 100644 --- a/internal/namespaces/instance/v1/custom_server_create.go +++ b/internal/namespaces/instance/v1/custom_server_create.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "io" "net" "reflect" "strconv" @@ -367,15 +366,16 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac // Cloud-init // if args.CloudInit != "" { - userData := make(map[string]io.Reader, len(args.CloudInit)) - userData["cloud-init"] = bytes.NewBufferString(args.CloudInit) - err := apiInstance.SetAllServerUserData(&instance.SetAllServerUserDataRequest{ + err := apiInstance.SetServerUserData(&instance.SetServerUserDataRequest{ Zone: args.Zone, ServerID: server.ID, - UserData: userData, + Key: "cloud-init", + Content: bytes.NewBufferString(args.CloudInit), }) if err != nil { - return nil, fmt.Errorf("error while setting up your cloud-init metadata: %s", err) + logger.Warningf("error while setting up your cloud-init metadata: %s. Note that the server is successfully created.", err) + } else { + logger.Debugf("cloud-init set") } } From 50da59138d25b1e24e59d3930d5c649772692ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Wed, 1 Jul 2020 15:35:37 +0200 Subject: [PATCH 5/5] Fix --- ...-usage-instance-server-update-usage.golden | 1 + .../namespaces/instance/v1/custom_server.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/cmd/scw/testdata/test-all-usage-instance-server-update-usage.golden b/cmd/scw/testdata/test-all-usage-instance-server-update-usage.golden index 3569e2e55f..7b0daa57aa 100644 --- a/cmd/scw/testdata/test-all-usage-instance-server-update-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-server-update-usage.golden @@ -28,6 +28,7 @@ ARGS: server-id UUID of the server [name] Name of the server [ip] IP that should be attached to the server (use ip=none to detach) + [cloud-init] The cloud-init script to use [boot-type] (local | bootscript | rescue) [tags.{index}] Tags of the server [bootscript] diff --git a/internal/namespaces/instance/v1/custom_server.go b/internal/namespaces/instance/v1/custom_server.go index 9b5c149678..81d7c97a26 100644 --- a/internal/namespaces/instance/v1/custom_server.go +++ b/internal/namespaces/instance/v1/custom_server.go @@ -1,6 +1,7 @@ package instance import ( + "bytes" "context" "fmt" "net" @@ -204,6 +205,7 @@ func serverUpdateBuilder(c *core.Command) *core.Command { PlacementGroupID *instance.NullableStringValue SecurityGroupID *string VolumeIDs *[]string + CloudInit string } c.ArgsType = reflect.TypeOf(instanceUpdateServerRequestCustom{}) @@ -229,6 +231,10 @@ func serverUpdateBuilder(c *core.Command) *core.Command { Name: "ip", Short: `IP that should be attached to the server (use ip=none to detach)`, }) + c.ArgSpecs.AddBefore("boot-type", &core.ArgSpec{ + Name: "cloud-init", + Short: "The cloud-init script to use", + }) c.Run = func(ctx context.Context, argsI interface{}) (i interface{}, e error) { customRequest := argsI.(*instanceUpdateServerRequestCustom) @@ -315,6 +321,19 @@ func serverUpdateBuilder(c *core.Command) *core.Command { customRequest.Volumes = &volumes } + // Set cloud-init + if customRequest.CloudInit != "" { + err := api.SetServerUserData(&instance.SetServerUserDataRequest{ + Zone: updateServerRequest.Zone, + ServerID: customRequest.ServerID, + Key: "cloud-init", + Content: bytes.NewBufferString(customRequest.CloudInit), + }) + if err != nil { + return nil, err + } + } + updateServerResponse, err := api.UpdateServer(updateServerRequest) if err != nil { return nil, err