From 0101eb1bb1ef0c0c275049b0cbc15dd05933a596 Mon Sep 17 00:00:00 2001 From: Roman Mingazeev Date: Mon, 23 Nov 2020 13:19:50 +0300 Subject: [PATCH 1/3] support merge cloud user-data --- builder/yandex/cloud_init.go | 45 ++++++++++++++++++++++++++ builder/yandex/cloud_init_test.go | 38 ++++++++++++++++++++++ builder/yandex/step_create_instance.go | 17 ++++++---- 3 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 builder/yandex/cloud_init.go create mode 100644 builder/yandex/cloud_init_test.go diff --git a/builder/yandex/cloud_init.go b/builder/yandex/cloud_init.go new file mode 100644 index 000000000..46ee4815c --- /dev/null +++ b/builder/yandex/cloud_init.go @@ -0,0 +1,45 @@ +package yandex + +import ( + "bytes" + "fmt" + "mime/multipart" + "net/textproto" +) + +const ( + defaultContentType = "text/cloud-config" + cloudInitIPv6Config = `#cloud-config +bootcmd: +- [ sh, -c, '/usr/bin/env dhclient -6 -D LL -nw -pf /run/dhclient_ipv6.eth0.pid -lf /var/lib/dhcp/dhclient_ipv6.eth0.leases eth0' ] +` +) + +// MergeCloudUserMetaData allow merge some user-data sections +func MergeCloudUserMetaData(usersData ...string) (string, error) { + buff := new(bytes.Buffer) + data := multipart.NewWriter(buff) + _, err := buff.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=\"%s\"\r\n", data.Boundary())) + if err != nil { + return "", err + } + _, err = buff.WriteString("MIME-Version: 1.0\r\n\r\n") + if err != nil { + return "", err + } + + for i, userData := range usersData { + w, err := data.CreatePart(textproto.MIMEHeader{ + "Content-Disposition": {fmt.Sprintf("attachment; filename=\"user-data-%d.yaml\"", i)}, + "Content-Type": {defaultContentType}, + }) + if err != nil { + return "", err + } + _, err = w.Write([]byte(userData)) + if err != nil { + return "", err + } + } + return buff.String(), nil +} diff --git a/builder/yandex/cloud_init_test.go b/builder/yandex/cloud_init_test.go new file mode 100644 index 000000000..7b00b10e0 --- /dev/null +++ b/builder/yandex/cloud_init_test.go @@ -0,0 +1,38 @@ +package yandex + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +const ( + data1 = ` +#cloud-config +bootcmd: + - cmd1 + - cmd2 +` + data2 = ` +#cloud-config +runcmd: + - touch "cmd3" + - cmd4 +` +) + +func TestCloudInitMerge(t *testing.T) { + merged, err := MergeCloudUserMetaData( + data1, + data2, + ) + + require.NoError(t, err) + require.NotEmpty(t, merged) + + require.Contains(t, merged, "cmd1") + require.Contains(t, merged, "cmd2") + require.Contains(t, merged, "\"cmd3\"") + require.Contains(t, merged, "cmd4") + +} diff --git a/builder/yandex/step_create_instance.go b/builder/yandex/step_create_instance.go index 757b24c2a..0e6a99e89 100644 --- a/builder/yandex/step_create_instance.go +++ b/builder/yandex/step_create_instance.go @@ -205,14 +205,17 @@ func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag) return stepHaltWithError(state, fmt.Errorf("Error preparing instance metadata: %s", err)) } - // TODO make part metadata prepare process if config.UseIPv6 { - // this ugly hack will replace user provided 'user-data' - userData := `#cloud-config -runcmd: -- [ sh, -c, '/sbin/dhclient -6 -D LL -nw -pf /run/dhclient_ipv6.eth0.pid -lf /var/lib/dhcp/dhclient_ipv6.eth0.leases eth0' ] -` - instanceMetadata["user-data"] = userData + ui.Say("Prepare user-data...") + + oldUserData, ok := instanceMetadata["user-data"] + if !ok { + oldUserData = "" + } + instanceMetadata["user-data"], err = MergeCloudUserMetaData(oldUserData, cloudInitIPv6Config) + if err != nil { + return stepHaltWithError(state, fmt.Errorf("Error merge user data configs: %s", err)) + } } req := &compute.CreateInstanceRequest{ From 2b8fcead23410aa4a3a55a92e79f1aa4395ad683 Mon Sep 17 00:00:00 2001 From: Roman Mingazeev Date: Mon, 23 Nov 2020 17:15:12 +0300 Subject: [PATCH 2/3] support shellscript --- builder/yandex/cloud_init.go | 22 +++++++++++++++++++--- builder/yandex/cloud_init_test.go | 5 +++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/builder/yandex/cloud_init.go b/builder/yandex/cloud_init.go index 46ee4815c..f1e63b6ea 100644 --- a/builder/yandex/cloud_init.go +++ b/builder/yandex/cloud_init.go @@ -5,10 +5,15 @@ import ( "fmt" "mime/multipart" "net/textproto" + "strings" +) + +const ( + defaultContentType = "text/cloud-config" + shellContentType = "text/x-shellscript" ) const ( - defaultContentType = "text/cloud-config" cloudInitIPv6Config = `#cloud-config bootcmd: - [ sh, -c, '/usr/bin/env dhclient -6 -D LL -nw -pf /run/dhclient_ipv6.eth0.pid -lf /var/lib/dhcp/dhclient_ipv6.eth0.leases eth0' ] @@ -30,8 +35,8 @@ func MergeCloudUserMetaData(usersData ...string) (string, error) { for i, userData := range usersData { w, err := data.CreatePart(textproto.MIMEHeader{ - "Content-Disposition": {fmt.Sprintf("attachment; filename=\"user-data-%d.yaml\"", i)}, - "Content-Type": {defaultContentType}, + "Content-Disposition": {fmt.Sprintf("attachment; filename=\"user-data-%d\"", i)}, + "Content-Type": {detectContentType(userData)}, }) if err != nil { return "", err @@ -43,3 +48,14 @@ func MergeCloudUserMetaData(usersData ...string) (string, error) { } return buff.String(), nil } + +func detectContentType(content string) string { + switch { + case strings.HasPrefix(content, "#!"): + return shellContentType + case strings.HasPrefix(content, "#cloud-config"): + return defaultContentType + } + + return defaultContentType +} diff --git a/builder/yandex/cloud_init_test.go b/builder/yandex/cloud_init_test.go index 7b00b10e0..aa2d5fcb3 100644 --- a/builder/yandex/cloud_init_test.go +++ b/builder/yandex/cloud_init_test.go @@ -19,12 +19,15 @@ runcmd: - touch "cmd3" - cmd4 ` + data3 = `#!/bin/bash +touch /test` ) func TestCloudInitMerge(t *testing.T) { merged, err := MergeCloudUserMetaData( data1, data2, + data3, ) require.NoError(t, err) @@ -35,4 +38,6 @@ func TestCloudInitMerge(t *testing.T) { require.Contains(t, merged, "\"cmd3\"") require.Contains(t, merged, "cmd4") + require.Contains(t, merged, "text/cloud-config") + require.Contains(t, merged, "text/x-shellscript") } From 937e3425e5eb3c22cc176faf32de9b60f9b466d3 Mon Sep 17 00:00:00 2001 From: Roman Mingazeev Date: Mon, 23 Nov 2020 17:44:49 +0300 Subject: [PATCH 3/3] add changelog record --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f320c681c..5161f2f41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ ### BUG FIXES * builder/amazon: Fix single `tag` interpolation to allow for templating engine usage. [GH-10224] +* builder/yandex: Fixed using cloud config when using IPv6 [GH-10297] ## 1.6.5 (October 30, 2020)