Merge pull request #10297 from Direnol/yandex/prepare-user-data

support merge cloud user-data
This commit is contained in:
Megan Marsh 2020-11-30 14:09:23 -08:00 committed by GitHub
commit 47f623a3a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 7 deletions

View File

@ -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]
* post-processort/yandex-export: added check of service account id
## 1.6.5 (October 30, 2020)

View File

@ -0,0 +1,61 @@
package yandex
import (
"bytes"
"fmt"
"mime/multipart"
"net/textproto"
"strings"
)
const (
defaultContentType = "text/cloud-config"
shellContentType = "text/x-shellscript"
)
const (
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\"", i)},
"Content-Type": {detectContentType(userData)},
})
if err != nil {
return "", err
}
_, err = w.Write([]byte(userData))
if err != nil {
return "", err
}
}
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
}

View File

@ -0,0 +1,43 @@
package yandex
import (
"testing"
"github.com/stretchr/testify/require"
)
const (
data1 = `
#cloud-config
bootcmd:
- cmd1
- cmd2
`
data2 = `
#cloud-config
runcmd:
- touch "cmd3"
- cmd4
`
data3 = `#!/bin/bash
touch /test`
)
func TestCloudInitMerge(t *testing.T) {
merged, err := MergeCloudUserMetaData(
data1,
data2,
data3,
)
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")
require.Contains(t, merged, "text/cloud-config")
require.Contains(t, merged, "text/x-shellscript")
}

View File

@ -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{