mirror of https://github.com/kubernetes/kops.git
Refactor nodeup script to avoid action-at-a-distance
This commit is contained in:
parent
648858a78a
commit
e2c28b062b
|
@ -11,7 +11,6 @@ go_library(
|
|||
"master_volumes.go",
|
||||
"names.go",
|
||||
"pki.go",
|
||||
"template_resource.go",
|
||||
],
|
||||
importpath = "k8s.io/kops/pkg/model",
|
||||
visibility = ["//visibility:public"],
|
||||
|
|
|
@ -18,7 +18,6 @@ package model
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
@ -26,7 +25,6 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kops/pkg/apis/kops/model"
|
||||
|
@ -227,11 +225,7 @@ func (b *BootstrapScriptBuilder) ResourceNodeUp(c *fi.ModelBuilderContext, ig *k
|
|||
|
||||
// Bastions can have AdditionalUserData, but if there isn't any skip this part
|
||||
if len(ig.Spec.AdditionalUserData) == 0 {
|
||||
templateResource, err := NewTemplateResource("nodeup", "", nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return templateResource, nil
|
||||
return fi.NewStringResource(""), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,36 +289,12 @@ func (b *BootstrapScript) Run(c *fi.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
functions := template.FuncMap{
|
||||
"NodeUpSourceAmd64": func() string {
|
||||
if b.builder.NodeUpAssets[architectures.ArchitectureAmd64] != nil {
|
||||
return strings.Join(b.builder.NodeUpAssets[architectures.ArchitectureAmd64].Locations, ",")
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"NodeUpSourceHashAmd64": func() string {
|
||||
if b.builder.NodeUpAssets[architectures.ArchitectureAmd64] != nil {
|
||||
return b.builder.NodeUpAssets[architectures.ArchitectureAmd64].Hash.Hex()
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"NodeUpSourceArm64": func() string {
|
||||
if b.builder.NodeUpAssets[architectures.ArchitectureArm64] != nil {
|
||||
return strings.Join(b.builder.NodeUpAssets[architectures.ArchitectureArm64].Locations, ",")
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"NodeUpSourceHashArm64": func() string {
|
||||
if b.builder.NodeUpAssets[architectures.ArchitectureArm64] != nil {
|
||||
return b.builder.NodeUpAssets[architectures.ArchitectureArm64].Hash.Hex()
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"KubeEnv": func() string {
|
||||
return config
|
||||
},
|
||||
var nodeupScript resources.NodeUpScript
|
||||
nodeupScript.NodeUpAssets = b.builder.NodeUpAssets
|
||||
nodeupScript.KubeEnv = config
|
||||
|
||||
"EnvironmentVariables": func() (string, error) {
|
||||
{
|
||||
nodeupScript.EnvironmentVariables = func() (string, error) {
|
||||
env, err := b.buildEnvironmentVariables(c.Cluster)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -342,13 +312,13 @@ func (b *BootstrapScript) Run(c *fi.Context) error {
|
|||
b.WriteString(fmt.Sprintf("export %s=%s\n", k, env[k]))
|
||||
}
|
||||
return b.String(), nil
|
||||
},
|
||||
}
|
||||
|
||||
"ProxyEnv": func() string {
|
||||
nodeupScript.ProxyEnv = func() (string, error) {
|
||||
return b.createProxyEnv(c.Cluster.Spec.EgressProxy)
|
||||
},
|
||||
}
|
||||
|
||||
"ClusterSpec": func() (string, error) {
|
||||
nodeupScript.ClusterSpec = func() (string, error) {
|
||||
cs := c.Cluster.Spec
|
||||
|
||||
spec := make(map[string]interface{})
|
||||
|
@ -399,24 +369,16 @@ func (b *BootstrapScript) Run(c *fi.Context) error {
|
|||
return "", fmt.Errorf("error converting cluster spec to yaml for inclusion within bootstrap script: %v", err)
|
||||
}
|
||||
return string(content), nil
|
||||
},
|
||||
|
||||
"CompressUserData": func() *bool {
|
||||
return b.ig.Spec.CompressUserData
|
||||
},
|
||||
|
||||
"GzipBase64": func(data string) (string, error) {
|
||||
return gzipBase64(data)
|
||||
},
|
||||
|
||||
"SetSysctls": func() string {
|
||||
// By setting some sysctls early, we avoid broken configurations that prevent nodeup download.
|
||||
// See https://github.com/kubernetes/kops/issues/10206 for details.
|
||||
return setSysctls()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
nodeupScriptResource, err := NewTemplateResource("nodeup", resources.NodeUpTemplate, functions, nil)
|
||||
nodeupScript.CompressUserData = fi.BoolValue(b.ig.Spec.CompressUserData)
|
||||
|
||||
// By setting some sysctls early, we avoid broken configurations that prevent nodeup download.
|
||||
// See https://github.com/kubernetes/kops/issues/10206 for details.
|
||||
nodeupScript.SetSysctls = setSysctls()
|
||||
|
||||
nodeupScriptResource, err := nodeupScript.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -437,7 +399,7 @@ func (b *BootstrapScript) Run(c *fi.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *BootstrapScript) createProxyEnv(ps *kops.EgressProxySpec) string {
|
||||
func (b *BootstrapScript) createProxyEnv(ps *kops.EgressProxySpec) (string, error) {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
if ps != nil && ps.HTTPProxy.Host != "" {
|
||||
|
@ -484,27 +446,7 @@ func (b *BootstrapScript) createProxyEnv(ps *kops.EgressProxySpec) string {
|
|||
buffer.WriteString("systemctl daemon-reload\n")
|
||||
buffer.WriteString("systemctl daemon-reexec\n")
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func gzipBase64(data string) (string, error) {
|
||||
var b bytes.Buffer
|
||||
gz := gzip.NewWriter(&b)
|
||||
|
||||
_, err := gz.Write([]byte(data))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = gz.Flush(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = gz.Close(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(b.Bytes()), nil
|
||||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
func setSysctls() string {
|
||||
|
|
|
@ -44,8 +44,10 @@ func Test_ProxyFunc(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
script := b.createProxyEnv(ps)
|
||||
|
||||
script, err := b.createProxyEnv(ps)
|
||||
if err != nil {
|
||||
t.Fatalf("createProxyEnv failed: %v", err)
|
||||
}
|
||||
if script == "" {
|
||||
t.Fatalf("script cannot be empty")
|
||||
}
|
||||
|
@ -56,7 +58,11 @@ func Test_ProxyFunc(t *testing.T) {
|
|||
|
||||
ps.ProxyExcludes = "www.google.com,www.kubernetes.io"
|
||||
|
||||
script = b.createProxyEnv(ps)
|
||||
script, err = b.createProxyEnv(ps)
|
||||
if err != nil {
|
||||
t.Fatalf("createProxyEnv failed: %v", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(script, "no_proxy="+ps.ProxyExcludes) {
|
||||
t.Fatalf("script not setting no_proxy properly")
|
||||
}
|
||||
|
|
|
@ -2,10 +2,18 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["nodeup.go"],
|
||||
srcs = [
|
||||
"nodeup.go",
|
||||
"template_resource.go",
|
||||
],
|
||||
importpath = "k8s.io/kops/pkg/model/resources",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//pkg/apis/kops:go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/kops:go_default_library",
|
||||
"//upup/pkg/fi:go_default_library",
|
||||
"//util/pkg/architectures:go_default_library",
|
||||
"//util/pkg/mirrors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
|
|
|
@ -19,14 +19,21 @@ package resources
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/textproto"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"k8s.io/kops/pkg/apis/kops"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/util/pkg/architectures"
|
||||
"k8s.io/kops/util/pkg/mirrors"
|
||||
)
|
||||
|
||||
var NodeUpTemplate = `#!/bin/bash
|
||||
var nodeUpTemplate = `#!/bin/bash
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
@ -165,6 +172,102 @@ download-release
|
|||
echo "== nodeup node config done =="
|
||||
`
|
||||
|
||||
// NodeUpScript is responsible for creating the nodeup script
|
||||
type NodeUpScript struct {
|
||||
NodeUpAssets map[architectures.Architecture]*mirrors.MirroredAsset
|
||||
KubeEnv string
|
||||
CompressUserData bool
|
||||
SetSysctls string
|
||||
ProxyEnv func() (string, error)
|
||||
EnvironmentVariables func() (string, error)
|
||||
ClusterSpec func() (string, error)
|
||||
}
|
||||
|
||||
func funcEmptyString() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (b *NodeUpScript) Build() (fi.Resource, error) {
|
||||
if b.ProxyEnv == nil {
|
||||
b.ProxyEnv = funcEmptyString
|
||||
}
|
||||
if b.EnvironmentVariables == nil {
|
||||
b.EnvironmentVariables = funcEmptyString
|
||||
}
|
||||
if b.ClusterSpec == nil {
|
||||
b.ClusterSpec = funcEmptyString
|
||||
}
|
||||
|
||||
functions := template.FuncMap{
|
||||
"NodeUpSourceAmd64": func() string {
|
||||
if b.NodeUpAssets[architectures.ArchitectureAmd64] != nil {
|
||||
return strings.Join(b.NodeUpAssets[architectures.ArchitectureAmd64].Locations, ",")
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"NodeUpSourceHashAmd64": func() string {
|
||||
if b.NodeUpAssets[architectures.ArchitectureAmd64] != nil {
|
||||
return b.NodeUpAssets[architectures.ArchitectureAmd64].Hash.Hex()
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"NodeUpSourceArm64": func() string {
|
||||
if b.NodeUpAssets[architectures.ArchitectureArm64] != nil {
|
||||
return strings.Join(b.NodeUpAssets[architectures.ArchitectureArm64].Locations, ",")
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"NodeUpSourceHashArm64": func() string {
|
||||
if b.NodeUpAssets[architectures.ArchitectureArm64] != nil {
|
||||
return b.NodeUpAssets[architectures.ArchitectureArm64].Hash.Hex()
|
||||
}
|
||||
return ""
|
||||
},
|
||||
|
||||
"KubeEnv": func() string {
|
||||
return b.KubeEnv
|
||||
},
|
||||
|
||||
"GzipBase64": func(data string) (string, error) {
|
||||
return gzipBase64(data)
|
||||
},
|
||||
|
||||
"CompressUserData": func() bool {
|
||||
return b.CompressUserData
|
||||
},
|
||||
|
||||
"SetSysctls": func() string {
|
||||
return b.SetSysctls
|
||||
},
|
||||
|
||||
"ProxyEnv": b.ProxyEnv,
|
||||
"EnvironmentVariables": b.EnvironmentVariables,
|
||||
"ClusterSpec": b.ClusterSpec,
|
||||
}
|
||||
|
||||
return newTemplateResource("nodeup", nodeUpTemplate, functions, nil)
|
||||
}
|
||||
|
||||
func gzipBase64(data string) (string, error) {
|
||||
var b bytes.Buffer
|
||||
gz := gzip.NewWriter(&b)
|
||||
|
||||
_, err := gz.Write([]byte(data))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = gz.Flush(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = gz.Close(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(b.Bytes()), nil
|
||||
}
|
||||
|
||||
// AWSMultipartMIME returns a MIME Multi Part Archive containing the nodeup (bootstrap) script
|
||||
// and any additional User Data passed to using AdditionalUserData in the IG Spec
|
||||
func AWSMultipartMIME(bootScript string, ig *kops.InstanceGroup) (string, error) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
)
|
||||
|
||||
func Test_NodeUpTabs(t *testing.T) {
|
||||
for i, line := range strings.Split(NodeUpTemplate, "\n") {
|
||||
for i, line := range strings.Split(nodeUpTemplate, "\n") {
|
||||
if strings.Contains(line, "\t") {
|
||||
t.Errorf("NodeUpTemplate contains unexpected character %q on line %d: %q", "\t", i, line)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package model
|
||||
package resources
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -35,7 +35,7 @@ type templateResource struct {
|
|||
|
||||
var _ fi.Resource = &templateResource{}
|
||||
|
||||
func NewTemplateResource(key string, definition string, functions template.FuncMap, context interface{}) (*templateResource, error) {
|
||||
func newTemplateResource(key string, definition string, functions template.FuncMap, context interface{}) (*templateResource, error) {
|
||||
r := &templateResource{
|
||||
key: key,
|
||||
definition: definition,
|
Loading…
Reference in New Issue