pkg/userdata/cloudinit/cloudinit.go (137 lines of code) (raw):
package cloudinit
import (
"bytes"
"fmt"
"strings"
"text/template"
etcdbootstrapv1 "github.com/aws/etcdadm-bootstrap-provider/api/v1beta1"
"github.com/aws/etcdadm-bootstrap-provider/pkg/userdata"
"github.com/pkg/errors"
capbk "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
)
const (
standardInitCommand = "etcdadm init"
standardJoinCommand = "etcdadm join %s"
// sentinelFileCommand writes a file to /run/cluster-api to signal successful Kubernetes bootstrapping in a way that
// works both for Linux and Windows OS.
sentinelFileCommand = "echo success > /run/cluster-api/bootstrap-success.complete"
cloudConfigHeader = `## template: jinja
#cloud-config
`
proxyConf = `
[Service]
Environment="HTTP_PROXY={{.HTTPProxy}}"
Environment="HTTPS_PROXY={{.HTTPSProxy}}"
Environment="NO_PROXY={{ stringsJoin .NoProxy "," }}"
`
registryMirrorConf = `
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."public.ecr.aws"]
endpoint = ["https://{{.Endpoint}}"]
[plugins."io.containerd.grpc.v1.cri".registry.configs."{{.Endpoint}}".tls]
{{- if not .CACert }}
insecure_skip_verify = true
{{- else }}
ca_file = "/etc/containerd/certs.d/{{.Endpoint}}/ca.crt"
{{- end }}
`
)
var containerdRestart = []string{"sudo systemctl daemon-reload", "sudo systemctl restart containerd"}
var defaultTemplateFuncMap = template.FuncMap{
"Indent": userdata.TemplateYAMLIndent,
}
func generate(kind string, tpl string, data interface{}) ([]byte, error) {
tm := template.New(kind).Funcs(defaultTemplateFuncMap)
if _, err := tm.Parse(filesTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse files template")
}
if _, err := tm.Parse(commandsTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse commands template")
}
if _, err := tm.Parse(ntpTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse ntp template")
}
if _, err := tm.Parse(usersTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse users template")
}
if _, err := tm.Parse(diskSetupTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse disk setup template")
}
if _, err := tm.Parse(fsSetupTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse fs setup template")
}
if _, err := tm.Parse(mountsTemplate); err != nil {
return nil, errors.Wrap(err, "failed to parse mounts template")
}
t, err := tm.Parse(tpl)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse %s template", kind)
}
var out bytes.Buffer
if err := t.Execute(&out, data); err != nil {
return nil, errors.Wrapf(err, "failed to generate %s template", kind)
}
return out.Bytes(), nil
}
func prepare(input *userdata.BaseUserData) error {
input.Header = cloudConfigHeader
input.WriteFiles = append(input.WriteFiles, input.AdditionalFiles...)
input.SentinelFileCommand = sentinelFileCommand
return nil
}
func buildEtcdadmArgs(config etcdbootstrapv1.EtcdadmConfigSpec) userdata.EtcdadmArgs {
return userdata.EtcdadmArgs{
Version: config.CloudInitConfig.Version,
EtcdReleaseURL: config.CloudInitConfig.EtcdReleaseURL,
InstallDir: config.CloudInitConfig.InstallDir,
CipherSuites: config.CipherSuites,
}
}
func setProxy(proxy *etcdbootstrapv1.ProxyConfiguration, input *userdata.BaseUserData) error {
if proxy == nil {
return nil
}
tmpl := template.New("proxy").Funcs(template.FuncMap{"stringsJoin": strings.Join})
t, err := tmpl.Parse(proxyConf)
if err != nil {
return fmt.Errorf("failed to parse proxy template: %v", err)
}
var out bytes.Buffer
if err = t.Execute(&out, proxy); err != nil {
return fmt.Errorf("error generating proxy config file: %v", err)
}
input.AdditionalFiles = append(input.AdditionalFiles, capbk.File{
Content: out.String(),
Owner: "root:root",
Path: "/etc/systemd/system/containerd.service.d/http-proxy.conf",
})
input.PreEtcdadmCommands = append(input.PreEtcdadmCommands, containerdRestart...)
return nil
}
func setRegistryMirror(registryMirror *etcdbootstrapv1.RegistryMirrorConfiguration, input *userdata.BaseUserData) error {
if registryMirror == nil {
return nil
}
tmpl := template.New("registryMirror")
t, err := tmpl.Parse(registryMirrorConf)
if err != nil {
return fmt.Errorf("failed to parse registryMirror template: %v", err)
}
var out bytes.Buffer
if err = t.Execute(&out, registryMirror); err != nil {
return fmt.Errorf("error generating registryMirror config file: %v", err)
}
input.AdditionalFiles = append(input.AdditionalFiles,
capbk.File{
Content: registryMirror.CACert,
Owner: "root:root",
Path: fmt.Sprintf("/etc/containerd/certs.d/%s/ca.crt", registryMirror.Endpoint),
},
capbk.File{
Content: out.String(),
Owner: "root:root",
Path: "/etc/containerd/config_append.toml",
},
)
input.PreEtcdadmCommands = append(input.PreEtcdadmCommands, `cat /etc/containerd/config_append.toml >> /etc/containerd/config.toml`)
input.PreEtcdadmCommands = append(input.PreEtcdadmCommands, containerdRestart...)
return nil
}