From e0461b92a9b9e2cffe8773b3cd683eb1d77be478 Mon Sep 17 00:00:00 2001 From: Kashif Saadat Date: Tue, 1 Aug 2017 22:50:38 +0100 Subject: [PATCH] Add ability to store partial cluster and instancegroup spec in userdata, so component config changes are detected and causes nodes to be updated --- cmd/kops/integration_test.go | 16 +- pkg/model/awsmodel/autoscalinggroup.go | 4 +- pkg/model/bootstrapscript.go | 52 ++++- pkg/model/bootstrapscript_test.go | 132 ++++++++++++- pkg/model/gcemodel/autoscalinggroup.go | 3 +- pkg/model/resources/nodeup.go | 8 + pkg/model/tests/data/bootstrapscript_0.txt | 187 ++++++++++++++++++ pkg/model/tests/data/bootstrapscript_1.txt | 179 +++++++++++++++++ pkg/model/vspheremodel/autoscalinggroup.go | 5 +- tests/integration/minimal/cloudformation.json | 6 +- upup/pkg/fi/cloudup/populate_cluster_spec.go | 1 + upup/pkg/fi/cloudup/vspheretasks/attachiso.go | 21 +- 12 files changed, 583 insertions(+), 31 deletions(-) create mode 100644 pkg/model/tests/data/bootstrapscript_0.txt create mode 100644 pkg/model/tests/data/bootstrapscript_1.txt diff --git a/cmd/kops/integration_test.go b/cmd/kops/integration_test.go index 29958623c0..7397abd1e7 100644 --- a/cmd/kops/integration_test.go +++ b/cmd/kops/integration_test.go @@ -22,11 +22,7 @@ import ( "crypto/rsa" "crypto/x509" "encoding/pem" - "golang.org/x/crypto/ssh" "io/ioutil" - "k8s.io/kops/cmd/kops/util" - "k8s.io/kops/pkg/diff" - "k8s.io/kops/pkg/testutils" "os" "path" "reflect" @@ -34,6 +30,12 @@ import ( "strings" "testing" "time" + + "golang.org/x/crypto/ssh" + + "k8s.io/kops/cmd/kops/util" + "k8s.io/kops/pkg/diff" + "k8s.io/kops/pkg/testutils" ) // TestMinimal runs the test on a minimum configuration, similar to kops create cluster minimal.example.com --zones us-west-1a @@ -322,8 +324,10 @@ func runTestCloudformation(t *testing.T, clusterName string, srcDir string, vers t.Fatalf("unexpected error reading expected cloudformation output: %v", err) } - if !bytes.Equal(actualCF, expectedCF) { - diffString := diff.FormatDiff(string(expectedCF), string(actualCF)) + expectedCFTrimmed := strings.TrimSpace(string(expectedCF)) + actualCFTrimmed := strings.TrimSpace(string(actualCF)) + if actualCFTrimmed != expectedCFTrimmed { + diffString := diff.FormatDiff(expectedCFTrimmed, actualCFTrimmed) t.Logf("diff:\n%s\n", diffString) t.Fatalf("cloudformation output differed from expected") diff --git a/pkg/model/awsmodel/autoscalinggroup.go b/pkg/model/awsmodel/autoscalinggroup.go index cd69ddd4dd..3f3437a138 100644 --- a/pkg/model/awsmodel/autoscalinggroup.go +++ b/pkg/model/awsmodel/autoscalinggroup.go @@ -18,7 +18,9 @@ package awsmodel import ( "fmt" + "github.com/golang/glog" + "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/model" "k8s.io/kops/upup/pkg/fi" @@ -117,7 +119,7 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error { return err } - if t.UserData, err = b.BootstrapScript.ResourceNodeUp(ig, b.Cluster.Spec.EgressProxy); err != nil { + if t.UserData, err = b.BootstrapScript.ResourceNodeUp(ig, &b.Cluster.Spec); err != nil { return err } diff --git a/pkg/model/bootstrapscript.go b/pkg/model/bootstrapscript.go index 09046b433b..4a9d29af79 100644 --- a/pkg/model/bootstrapscript.go +++ b/pkg/model/bootstrapscript.go @@ -24,6 +24,8 @@ import ( "strings" "text/template" + "github.com/ghodss/yaml" + "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/nodeup" "k8s.io/kops/pkg/model/resources" @@ -37,7 +39,9 @@ type BootstrapScript struct { NodeUpConfigBuilder func(ig *kops.InstanceGroup) (*nodeup.Config, error) } -func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, ps *kops.EgressProxySpec) (*fi.ResourceHolder, error) { +// ResourceNodeUp generates and returns a nodeup (bootstrap) script from a +// template file, substituting in specific env vars & cluster spec configuration +func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, cs *kops.ClusterSpec) (*fi.ResourceHolder, error) { if ig.Spec.Role == kops.InstanceGroupRoleBastion { // Bastions are just bare machines (currently), used as SSH jump-hosts return nil, nil @@ -77,7 +81,7 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, ps *kops.Egress }, "ProxyEnv": func() string { - return b.createProxyEnv(ps) + return b.createProxyEnv(cs.EgressProxy) }, "AWS_REGION": func() string { if os.Getenv("AWS_REGION") != "" { @@ -86,6 +90,40 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, ps *kops.Egress } return "" }, + + "ClusterSpec": func() (string, error) { + spec := make(map[string]interface{}) + spec["cloudConfig"] = cs.CloudConfig + spec["docker"] = cs.Docker + spec["kubelet"] = cs.Kubelet + spec["kubeProxy"] = cs.KubeProxy + + if ig.IsMaster() { + spec["kubeAPIServer"] = cs.KubeAPIServer + spec["kubeControllerManager"] = cs.KubeControllerManager + spec["kubeScheduler"] = cs.KubeScheduler + spec["masterKubelet"] = cs.MasterKubelet + } + + content, err := yaml.Marshal(spec) + if err != nil { + return "", fmt.Errorf("error converting cluster spec to yaml for inclusion within bootstrap script: %v", err) + } + return string(content), nil + }, + + "IGSpec": func() (string, error) { + spec := make(map[string]interface{}) + spec["kubelet"] = ig.Spec.Kubelet + spec["nodeLabels"] = ig.Spec.NodeLabels + spec["taints"] = ig.Spec.Taints + + content, err := yaml.Marshal(spec) + if err != nil { + return "", fmt.Errorf("error converting instancegroup spec to yaml for inclusion within bootstrap script: %v", err) + } + return string(content), nil + }, } templateResource, err := NewTemplateResource("nodeup", resources.AWSNodeUpTemplate, functions, nil) @@ -99,22 +137,22 @@ func (b *BootstrapScript) createProxyEnv(ps *kops.EgressProxySpec) string { var buffer bytes.Buffer if ps != nil && ps.HTTPProxy.Host != "" { - var httpProxyUrl string + var httpProxyURL string // TODO double check that all the code does this // TODO move this into a validate so we can enforce the string syntax if !strings.HasPrefix(ps.HTTPProxy.Host, "http://") { - httpProxyUrl = "http://" + httpProxyURL = "http://" } if ps.HTTPProxy.Port != 0 { - httpProxyUrl += ps.HTTPProxy.Host + ":" + strconv.Itoa(ps.HTTPProxy.Port) + httpProxyURL += ps.HTTPProxy.Host + ":" + strconv.Itoa(ps.HTTPProxy.Port) } else { - httpProxyUrl += ps.HTTPProxy.Host + httpProxyURL += ps.HTTPProxy.Host } // Set base env variables - buffer.WriteString("export http_proxy=" + httpProxyUrl + "\n") + buffer.WriteString("export http_proxy=" + httpProxyURL + "\n") buffer.WriteString("export https_proxy=${http_proxy}\n") buffer.WriteString("export no_proxy=" + ps.ProxyExcludes + "\n") buffer.WriteString("export NO_PROXY=${no_proxy}\n") diff --git a/pkg/model/bootstrapscript_test.go b/pkg/model/bootstrapscript_test.go index 3c6b738dbd..46a61a5446 100644 --- a/pkg/model/bootstrapscript_test.go +++ b/pkg/model/bootstrapscript_test.go @@ -17,10 +17,12 @@ limitations under the License. package model import ( + "io/ioutil" "strings" "testing" "k8s.io/kops/pkg/apis/kops" + "k8s.io/kops/pkg/apis/nodeup" ) func Test_ProxyFunc(t *testing.T) { @@ -49,5 +51,133 @@ func Test_ProxyFunc(t *testing.T) { if !strings.Contains(script, "export no_proxy="+ps.ProxyExcludes) { t.Fatalf("script not setting no_proxy properly") } - +} + +func TestBootstrapUserData(t *testing.T) { + cs := []struct { + Role kops.InstanceGroupRole + ExpectedFilePath string + }{ + { + Role: "Master", + ExpectedFilePath: "tests/data/bootstrapscript_0.txt", + }, + { + Role: "Node", + ExpectedFilePath: "tests/data/bootstrapscript_1.txt", + }, + } + + for i, x := range cs { + spec := makeTestCluster().Spec + group := makeTestInstanceGroup(x.Role) + + renderNodeUpConfig := func(ig *kops.InstanceGroup) (*nodeup.Config, error) { + return &nodeup.Config{}, nil + } + + bs := &BootstrapScript{ + NodeUpSource: "NUSource", + NodeUpSourceHash: "NUSHash", + NodeUpConfigBuilder: renderNodeUpConfig, + } + + res, err := bs.ResourceNodeUp(group, &spec) + if err != nil { + t.Errorf("case %d failed to create nodeup resource. error: %s", i, err) + continue + } + + actual, err := res.AsString() + if err != nil { + t.Errorf("case %d failed to render nodeup resource. error: %s", i, err) + continue + } + + expectedBytes, err := ioutil.ReadFile(x.ExpectedFilePath) + if err != nil { + t.Fatalf("unexpected error reading ExpectedFilePath %q: %v", x.ExpectedFilePath, err) + } + + if actual != string(expectedBytes) { + t.Errorf("case %d, expected: %s. got: %s", i, string(expectedBytes), actual) + } + } +} + +func makeTestCluster() *kops.Cluster { + return &kops.Cluster{ + Spec: kops.ClusterSpec{ + CloudProvider: "aws", + KubernetesVersion: "1.7.0", + Subnets: []kops.ClusterSubnetSpec{ + {Name: "test", Zone: "eu-west-1a"}, + }, + NonMasqueradeCIDR: "10.100.0.0/16", + EtcdClusters: []*kops.EtcdClusterSpec{ + { + Name: "main", + Members: []*kops.EtcdMemberSpec{ + { + Name: "test", + InstanceGroup: s("ig-1"), + }, + }, + }, + }, + NetworkCIDR: "10.79.0.0/24", + CloudConfig: &kops.CloudConfiguration{ + NodeTags: s("something"), + }, + Docker: &kops.DockerConfig{ + LogLevel: s("INFO"), + }, + KubeAPIServer: &kops.KubeAPIServerConfig{ + Image: "CoreOS", + }, + KubeControllerManager: &kops.KubeControllerManagerConfig{ + CloudProvider: "aws", + }, + KubeProxy: &kops.KubeProxyConfig{ + CPURequest: "30m", + FeatureGates: map[string]string{ + "AdvancedAuditing": "true", + }, + }, + KubeScheduler: &kops.KubeSchedulerConfig{ + Image: "SomeImage", + }, + Kubelet: &kops.KubeletConfigSpec{ + KubeconfigPath: "/etc/kubernetes/config.txt", + }, + MasterKubelet: &kops.KubeletConfigSpec{ + KubeconfigPath: "/etc/kubernetes/config.cfg", + }, + EgressProxy: &kops.EgressProxySpec{ + HTTPProxy: kops.HTTPProxy{ + Host: "example.com", + Port: 80, + }, + }, + }, + } +} + +func makeTestInstanceGroup(role kops.InstanceGroupRole) *kops.InstanceGroup { + return &kops.InstanceGroup{ + Spec: kops.InstanceGroupSpec{ + Kubelet: &kops.KubeletConfigSpec{ + KubeconfigPath: "/etc/kubernetes/igconfig.txt", + }, + NodeLabels: map[string]string{ + "labelname": "labelvalue", + "label2": "value2", + }, + Role: role, + Taints: []string{ + "key1=value1:NoSchedule", + "key2=value2:NoExecute", + }, + }, + } } diff --git a/pkg/model/gcemodel/autoscalinggroup.go b/pkg/model/gcemodel/autoscalinggroup.go index c0ed53caa0..8ae8ba177a 100644 --- a/pkg/model/gcemodel/autoscalinggroup.go +++ b/pkg/model/gcemodel/autoscalinggroup.go @@ -18,6 +18,7 @@ package gcemodel import ( "fmt" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/model" @@ -44,7 +45,7 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error { for _, ig := range b.InstanceGroups { name := b.SafeObjectName(ig.ObjectMeta.Name) - startupScript, err := b.BootstrapScript.ResourceNodeUp(ig, b.Cluster.Spec.EgressProxy) + startupScript, err := b.BootstrapScript.ResourceNodeUp(ig, &b.Cluster.Spec) if err != nil { return err } diff --git a/pkg/model/resources/nodeup.go b/pkg/model/resources/nodeup.go index ef9f5015b6..bcb1e49f21 100644 --- a/pkg/model/resources/nodeup.go +++ b/pkg/model/resources/nodeup.go @@ -141,6 +141,14 @@ function download-release() { echo "== nodeup node config starting ==" ensure-install-dir +cat > cluster_spec.yaml << __EOF_CLUSTER_SPEC +{{ ClusterSpec }} +__EOF_CLUSTER_SPEC + +cat > ig_spec.yaml << __EOF_IG_SPEC +{{ IGSpec }} +__EOF_IG_SPEC + cat > kube_env.yaml << __EOF_KUBE_ENV {{ KubeEnv }} __EOF_KUBE_ENV diff --git a/pkg/model/tests/data/bootstrapscript_0.txt b/pkg/model/tests/data/bootstrapscript_0.txt new file mode 100644 index 0000000000..3bc00be24c --- /dev/null +++ b/pkg/model/tests/data/bootstrapscript_0.txt @@ -0,0 +1,187 @@ +#!/bin/bash +# Copyright 2016 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +NODEUP_URL=NUSource +NODEUP_HASH=NUSHash + + + + +export http_proxy=http://example.com:80 +export https_proxy=${http_proxy} +export no_proxy= +export NO_PROXY=${no_proxy} +echo "export http_proxy=${http_proxy}" >> /etc/default/docker +echo "export https_proxy=${http_proxy}" >> /etc/default/docker +echo "export no_proxy=${no_proxy}" >> /etc/default/docker +echo "export NO_PROXY=${no_proxy}" >> /etc/default/docker +echo "export http_proxy=${http_proxy}" >> /etc/environment +echo "export https_proxy=${http_proxy}" >> /etc/environment +echo "export no_proxy=${no_proxy}" >> /etc/environment +echo "export NO_PROXY=${no_proxy}" >> /etc/environment +echo DefaultEnvironment=\"http_proxy=${http_proxy}\" \"https_proxy=${http_proxy}\"echo DefaultEnvironment=\"http_proxy=${http_proxy}\" \"https_proxy=${http_proxy}\" \"NO_PROXY=${no_proxy}\" \"no_proxy=${no_proxy}\" >> /etc/systemd/system.conf +source /etc/environment +systemctl daemon-reload +systemctl daemon-reexec +if [ -f /etc/lsb-release ] || [ -f /etc/debian_version ]; then + echo "Acquire::http::Proxy \"${http_proxy}\";" > /etc/apt/apt.conf.d/30proxy +elif [ -f /etc/redhat-release ]; then + echo "http_proxy=${http_proxy}" >> /etc/yum.conf +fi + + +function ensure-install-dir() { + INSTALL_DIR="/var/cache/kubernetes-install" + # On ContainerOS, we install to /var/lib/toolbox install (because of noexec) + if [[ -d /var/lib/toolbox ]]; then + INSTALL_DIR="/var/lib/toolbox/kubernetes-install" + fi + mkdir -p ${INSTALL_DIR} + cd ${INSTALL_DIR} +} + +# Retry a download until we get it. Takes a hash and a set of URLs. +# +# $1 is the sha1 of the URL. Can be "" if the sha1 is unknown. +# $2+ are the URLs to download. +download-or-bust() { + local -r hash="$1" + shift 1 + + urls=( $* ) + while true; do + for url in "${urls[@]}"; do + local file="${url##*/}" + rm -f "${file}" + if ! curl -f --ipv4 -Lo "${file}" --connect-timeout 20 --retry 6 --retry-delay 10 "${url}"; then + echo "== Failed to download ${url}. Retrying. ==" + elif [[ -n "${hash}" ]] && ! validate-hash "${file}" "${hash}"; then + echo "== Hash validation of ${url} failed. Retrying. ==" + else + if [[ -n "${hash}" ]]; then + echo "== Downloaded ${url} (SHA1 = ${hash}) ==" + else + echo "== Downloaded ${url} ==" + fi + return + fi + done + + echo "All downloads failed; sleeping before retrying" + sleep 60 + done +} + +validate-hash() { + local -r file="$1" + local -r expected="$2" + local actual + + actual=$(sha1sum ${file} | awk '{ print $1 }') || true + if [[ "${actual}" != "${expected}" ]]; then + echo "== ${file} corrupted, sha1 ${actual} doesn't match expected ${expected} ==" + return 1 + fi +} + +function split-commas() { + echo $1 | tr "," "\n" +} + +function try-download-release() { + # TODO(zmerlynn): Now we REALLY have no excuse not to do the reboot + # optimization. + + local -r nodeup_urls=( $(split-commas "${NODEUP_URL}") ) + local -r nodeup_filename="${nodeup_urls[0]##*/}" + if [[ -n "${NODEUP_HASH:-}" ]]; then + local -r nodeup_hash="${NODEUP_HASH}" + else + # TODO: Remove? + echo "Downloading sha1 (not found in env)" + download-or-bust "" "${nodeup_urls[@]/%/.sha1}" + local -r nodeup_hash=$(cat "${nodeup_filename}.sha1") + fi + + echo "Downloading nodeup (${nodeup_urls[@]})" + download-or-bust "${nodeup_hash}" "${nodeup_urls[@]}" + + chmod +x nodeup +} + +function download-release() { + # In case of failure checking integrity of release, retry. + until try-download-release; do + sleep 15 + echo "Couldn't download release. Retrying..." + done + + echo "Running nodeup" + # We can't run in the foreground because of https://github.com/docker/docker/issues/23793 + ( cd ${INSTALL_DIR}; ./nodeup --install-systemd-unit --conf=${INSTALL_DIR}/kube_env.yaml --v=8 ) +} + +#################################################################################### + +/bin/systemd-machine-id-setup || echo "failed to set up ensure machine-id configured" + +echo "== nodeup node config starting ==" +ensure-install-dir + +cat > cluster_spec.yaml << __EOF_CLUSTER_SPEC +cloudConfig: + nodeTags: something +docker: + logLevel: INFO +kubeAPIServer: + image: CoreOS +kubeControllerManager: + cloudProvider: aws +kubeProxy: + cpuRequest: 30m + featureGates: + AdvancedAuditing: "true" +kubeScheduler: + image: SomeImage +kubelet: + kubeconfigPath: /etc/kubernetes/config.txt +masterKubelet: + kubeconfigPath: /etc/kubernetes/config.cfg + +__EOF_CLUSTER_SPEC + +cat > ig_spec.yaml << __EOF_IG_SPEC +kubelet: + kubeconfigPath: /etc/kubernetes/igconfig.txt +nodeLabels: + label2: value2 + labelname: labelvalue +taints: +- key1=value1:NoSchedule +- key2=value2:NoExecute + +__EOF_IG_SPEC + +cat > kube_env.yaml << __EOF_KUBE_ENV +{} + +__EOF_KUBE_ENV + +download-release +echo "== nodeup node config done ==" diff --git a/pkg/model/tests/data/bootstrapscript_1.txt b/pkg/model/tests/data/bootstrapscript_1.txt new file mode 100644 index 0000000000..e81aabfe87 --- /dev/null +++ b/pkg/model/tests/data/bootstrapscript_1.txt @@ -0,0 +1,179 @@ +#!/bin/bash +# Copyright 2016 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +NODEUP_URL=NUSource +NODEUP_HASH=NUSHash + + + + +export http_proxy=http://example.com:80 +export https_proxy=${http_proxy} +export no_proxy= +export NO_PROXY=${no_proxy} +echo "export http_proxy=${http_proxy}" >> /etc/default/docker +echo "export https_proxy=${http_proxy}" >> /etc/default/docker +echo "export no_proxy=${no_proxy}" >> /etc/default/docker +echo "export NO_PROXY=${no_proxy}" >> /etc/default/docker +echo "export http_proxy=${http_proxy}" >> /etc/environment +echo "export https_proxy=${http_proxy}" >> /etc/environment +echo "export no_proxy=${no_proxy}" >> /etc/environment +echo "export NO_PROXY=${no_proxy}" >> /etc/environment +echo DefaultEnvironment=\"http_proxy=${http_proxy}\" \"https_proxy=${http_proxy}\"echo DefaultEnvironment=\"http_proxy=${http_proxy}\" \"https_proxy=${http_proxy}\" \"NO_PROXY=${no_proxy}\" \"no_proxy=${no_proxy}\" >> /etc/systemd/system.conf +source /etc/environment +systemctl daemon-reload +systemctl daemon-reexec +if [ -f /etc/lsb-release ] || [ -f /etc/debian_version ]; then + echo "Acquire::http::Proxy \"${http_proxy}\";" > /etc/apt/apt.conf.d/30proxy +elif [ -f /etc/redhat-release ]; then + echo "http_proxy=${http_proxy}" >> /etc/yum.conf +fi + + +function ensure-install-dir() { + INSTALL_DIR="/var/cache/kubernetes-install" + # On ContainerOS, we install to /var/lib/toolbox install (because of noexec) + if [[ -d /var/lib/toolbox ]]; then + INSTALL_DIR="/var/lib/toolbox/kubernetes-install" + fi + mkdir -p ${INSTALL_DIR} + cd ${INSTALL_DIR} +} + +# Retry a download until we get it. Takes a hash and a set of URLs. +# +# $1 is the sha1 of the URL. Can be "" if the sha1 is unknown. +# $2+ are the URLs to download. +download-or-bust() { + local -r hash="$1" + shift 1 + + urls=( $* ) + while true; do + for url in "${urls[@]}"; do + local file="${url##*/}" + rm -f "${file}" + if ! curl -f --ipv4 -Lo "${file}" --connect-timeout 20 --retry 6 --retry-delay 10 "${url}"; then + echo "== Failed to download ${url}. Retrying. ==" + elif [[ -n "${hash}" ]] && ! validate-hash "${file}" "${hash}"; then + echo "== Hash validation of ${url} failed. Retrying. ==" + else + if [[ -n "${hash}" ]]; then + echo "== Downloaded ${url} (SHA1 = ${hash}) ==" + else + echo "== Downloaded ${url} ==" + fi + return + fi + done + + echo "All downloads failed; sleeping before retrying" + sleep 60 + done +} + +validate-hash() { + local -r file="$1" + local -r expected="$2" + local actual + + actual=$(sha1sum ${file} | awk '{ print $1 }') || true + if [[ "${actual}" != "${expected}" ]]; then + echo "== ${file} corrupted, sha1 ${actual} doesn't match expected ${expected} ==" + return 1 + fi +} + +function split-commas() { + echo $1 | tr "," "\n" +} + +function try-download-release() { + # TODO(zmerlynn): Now we REALLY have no excuse not to do the reboot + # optimization. + + local -r nodeup_urls=( $(split-commas "${NODEUP_URL}") ) + local -r nodeup_filename="${nodeup_urls[0]##*/}" + if [[ -n "${NODEUP_HASH:-}" ]]; then + local -r nodeup_hash="${NODEUP_HASH}" + else + # TODO: Remove? + echo "Downloading sha1 (not found in env)" + download-or-bust "" "${nodeup_urls[@]/%/.sha1}" + local -r nodeup_hash=$(cat "${nodeup_filename}.sha1") + fi + + echo "Downloading nodeup (${nodeup_urls[@]})" + download-or-bust "${nodeup_hash}" "${nodeup_urls[@]}" + + chmod +x nodeup +} + +function download-release() { + # In case of failure checking integrity of release, retry. + until try-download-release; do + sleep 15 + echo "Couldn't download release. Retrying..." + done + + echo "Running nodeup" + # We can't run in the foreground because of https://github.com/docker/docker/issues/23793 + ( cd ${INSTALL_DIR}; ./nodeup --install-systemd-unit --conf=${INSTALL_DIR}/kube_env.yaml --v=8 ) +} + +#################################################################################### + +/bin/systemd-machine-id-setup || echo "failed to set up ensure machine-id configured" + +echo "== nodeup node config starting ==" +ensure-install-dir + +cat > cluster_spec.yaml << __EOF_CLUSTER_SPEC +cloudConfig: + nodeTags: something +docker: + logLevel: INFO +kubeProxy: + cpuRequest: 30m + featureGates: + AdvancedAuditing: "true" +kubelet: + kubeconfigPath: /etc/kubernetes/config.txt + +__EOF_CLUSTER_SPEC + +cat > ig_spec.yaml << __EOF_IG_SPEC +kubelet: + kubeconfigPath: /etc/kubernetes/igconfig.txt +nodeLabels: + label2: value2 + labelname: labelvalue +taints: +- key1=value1:NoSchedule +- key2=value2:NoExecute + +__EOF_IG_SPEC + +cat > kube_env.yaml << __EOF_KUBE_ENV +{} + +__EOF_KUBE_ENV + +download-release +echo "== nodeup node config done ==" diff --git a/pkg/model/vspheremodel/autoscalinggroup.go b/pkg/model/vspheremodel/autoscalinggroup.go index a97753d494..13e161a1a9 100644 --- a/pkg/model/vspheremodel/autoscalinggroup.go +++ b/pkg/model/vspheremodel/autoscalinggroup.go @@ -19,11 +19,12 @@ package vspheremodel // autoscalinggroup is a model for vSphere cloud. It's responsible for building tasks, necessary for kubernetes cluster deployment. import ( + "strconv" + "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/model" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/vspheretasks" - "strconv" ) // AutoscalingGroupModelBuilder configures AutoscalingGroup objects @@ -61,7 +62,7 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error { VM: createVmTask, IG: ig, BootstrapScript: b.BootstrapScript, - EtcdClusters: b.Cluster.Spec.EtcdClusters, + Spec: &b.Cluster.Spec, } c.AddTask(attachISOTask) diff --git a/tests/integration/minimal/cloudformation.json b/tests/integration/minimal/cloudformation.json index add161f896..abf42e84e1 100644 --- a/tests/integration/minimal/cloudformation.json +++ b/tests/integration/minimal/cloudformation.json @@ -93,7 +93,7 @@ "Ref": "AWSEC2SecurityGroupmastersminimalexamplecom" } ], - "UserData": "IyEvYmluL2Jhc2gKIyBDb3B5cmlnaHQgMjAxNiBUaGUgS3ViZXJuZXRlcyBBdXRob3JzIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiMKIyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKIyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiMgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiMKIyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiMKIyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKIyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KIyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiMgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgpzZXQgLW8gZXJyZXhpdApzZXQgLW8gbm91bnNldApzZXQgLW8gcGlwZWZhaWwKCk5PREVVUF9VUkw9aHR0cHM6Ly9rdWJldXB2Mi5zMy5hbWF6b25hd3MuY29tL2tvcHMvMS41LjAvbGludXgvYW1kNjQvbm9kZXVwCk5PREVVUF9IQVNIPQoKCgoKCgpmdW5jdGlvbiBlbnN1cmUtaW5zdGFsbC1kaXIoKSB7CiAgSU5TVEFMTF9ESVI9Ii92YXIvY2FjaGUva3ViZXJuZXRlcy1pbnN0YWxsIgogICMgT24gQ29udGFpbmVyT1MsIHdlIGluc3RhbGwgdG8gL3Zhci9saWIvdG9vbGJveCBpbnN0YWxsIChiZWNhdXNlIG9mIG5vZXhlYykKICBpZiBbWyAtZCAvdmFyL2xpYi90b29sYm94IF1dOyB0aGVuCiAgICBJTlNUQUxMX0RJUj0iL3Zhci9saWIvdG9vbGJveC9rdWJlcm5ldGVzLWluc3RhbGwiCiAgZmkKICBta2RpciAtcCAke0lOU1RBTExfRElSfQogIGNkICR7SU5TVEFMTF9ESVJ9Cn0KCiMgUmV0cnkgYSBkb3dubG9hZCB1bnRpbCB3ZSBnZXQgaXQuIFRha2VzIGEgaGFzaCBhbmQgYSBzZXQgb2YgVVJMcy4KIwojICQxIGlzIHRoZSBzaGExIG9mIHRoZSBVUkwuIENhbiBiZSAiIiBpZiB0aGUgc2hhMSBpcyB1bmtub3duLgojICQyKyBhcmUgdGhlIFVSTHMgdG8gZG93bmxvYWQuCmRvd25sb2FkLW9yLWJ1c3QoKSB7CiAgbG9jYWwgLXIgaGFzaD0iJDEiCiAgc2hpZnQgMQoKICB1cmxzPSggJCogKQogIHdoaWxlIHRydWU7IGRvCiAgICBmb3IgdXJsIGluICIke3VybHNbQF19IjsgZG8KICAgICAgbG9jYWwgZmlsZT0iJHt1cmwjIyovfSIKICAgICAgcm0gLWYgIiR7ZmlsZX0iCiAgICAgIGlmICEgY3VybCAtZiAtLWlwdjQgLUxvICIke2ZpbGV9IiAtLWNvbm5lY3QtdGltZW91dCAyMCAtLXJldHJ5IDYgLS1yZXRyeS1kZWxheSAxMCAiJHt1cmx9IjsgdGhlbgogICAgICAgIGVjaG8gIj09IEZhaWxlZCB0byBkb3dubG9hZCAke3VybH0uIFJldHJ5aW5nLiA9PSIKICAgICAgZWxpZiBbWyAtbiAiJHtoYXNofSIgXV0gJiYgISB2YWxpZGF0ZS1oYXNoICIke2ZpbGV9IiAiJHtoYXNofSI7IHRoZW4KICAgICAgICBlY2hvICI9PSBIYXNoIHZhbGlkYXRpb24gb2YgJHt1cmx9IGZhaWxlZC4gUmV0cnlpbmcuID09IgogICAgICBlbHNlCiAgICAgICAgaWYgW1sgLW4gIiR7aGFzaH0iIF1dOyB0aGVuCiAgICAgICAgICBlY2hvICI9PSBEb3dubG9hZGVkICR7dXJsfSAoU0hBMSA9ICR7aGFzaH0pID09IgogICAgICAgIGVsc2UKICAgICAgICAgIGVjaG8gIj09IERvd25sb2FkZWQgJHt1cmx9ID09IgogICAgICAgIGZpCiAgICAgICAgcmV0dXJuCiAgICAgIGZpCiAgICBkb25lCgogICAgZWNobyAiQWxsIGRvd25sb2FkcyBmYWlsZWQ7IHNsZWVwaW5nIGJlZm9yZSByZXRyeWluZyIKICAgIHNsZWVwIDYwCiAgZG9uZQp9Cgp2YWxpZGF0ZS1oYXNoKCkgewogIGxvY2FsIC1yIGZpbGU9IiQxIgogIGxvY2FsIC1yIGV4cGVjdGVkPSIkMiIKICBsb2NhbCBhY3R1YWwKCiAgYWN0dWFsPSQoc2hhMXN1bSAke2ZpbGV9IHwgYXdrICd7IHByaW50ICQxIH0nKSB8fCB0cnVlCiAgaWYgW1sgIiR7YWN0dWFsfSIgIT0gIiR7ZXhwZWN0ZWR9IiBdXTsgdGhlbgogICAgZWNobyAiPT0gJHtmaWxlfSBjb3JydXB0ZWQsIHNoYTEgJHthY3R1YWx9IGRvZXNuJ3QgbWF0Y2ggZXhwZWN0ZWQgJHtleHBlY3RlZH0gPT0iCiAgICByZXR1cm4gMQogIGZpCn0KCmZ1bmN0aW9uIHNwbGl0LWNvbW1hcygpIHsKICBlY2hvICQxIHwgdHIgIiwiICJcbiIKfQoKZnVuY3Rpb24gdHJ5LWRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBUT0RPKHptZXJseW5uKTogTm93IHdlIFJFQUxMWSBoYXZlIG5vIGV4Y3VzZSBub3QgdG8gZG8gdGhlIHJlYm9vdAogICMgb3B0aW1pemF0aW9uLgoKICBsb2NhbCAtciBub2RldXBfdXJscz0oICQoc3BsaXQtY29tbWFzICIke05PREVVUF9VUkx9IikgKQogIGxvY2FsIC1yIG5vZGV1cF9maWxlbmFtZT0iJHtub2RldXBfdXJsc1swXSMjKi99IgogIGlmIFtbIC1uICIke05PREVVUF9IQVNIOi19IiBdXTsgdGhlbgogICAgbG9jYWwgLXIgbm9kZXVwX2hhc2g9IiR7Tk9ERVVQX0hBU0h9IgogIGVsc2UKICAjIFRPRE86IFJlbW92ZT8KICAgIGVjaG8gIkRvd25sb2FkaW5nIHNoYTEgKG5vdCBmb3VuZCBpbiBlbnYpIgogICAgZG93bmxvYWQtb3ItYnVzdCAiIiAiJHtub2RldXBfdXJsc1tAXS8lLy5zaGExfSIKICAgIGxvY2FsIC1yIG5vZGV1cF9oYXNoPSQoY2F0ICIke25vZGV1cF9maWxlbmFtZX0uc2hhMSIpCiAgZmkKCiAgZWNobyAiRG93bmxvYWRpbmcgbm9kZXVwICgke25vZGV1cF91cmxzW0BdfSkiCiAgZG93bmxvYWQtb3ItYnVzdCAiJHtub2RldXBfaGFzaH0iICIke25vZGV1cF91cmxzW0BdfSIKCiAgY2htb2QgK3ggbm9kZXVwCn0KCmZ1bmN0aW9uIGRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBJbiBjYXNlIG9mIGZhaWx1cmUgY2hlY2tpbmcgaW50ZWdyaXR5IG9mIHJlbGVhc2UsIHJldHJ5LgogIHVudGlsIHRyeS1kb3dubG9hZC1yZWxlYXNlOyBkbwogICAgc2xlZXAgMTUKICAgIGVjaG8gIkNvdWxkbid0IGRvd25sb2FkIHJlbGVhc2UuIFJldHJ5aW5nLi4uIgogIGRvbmUKCiAgZWNobyAiUnVubmluZyBub2RldXAiCiAgIyBXZSBjYW4ndCBydW4gaW4gdGhlIGZvcmVncm91bmQgYmVjYXVzZSBvZiBodHRwczovL2dpdGh1Yi5jb20vZG9ja2VyL2RvY2tlci9pc3N1ZXMvMjM3OTMKICAoIGNkICR7SU5TVEFMTF9ESVJ9OyAuL25vZGV1cCAtLWluc3RhbGwtc3lzdGVtZC11bml0IC0tY29uZj0ke0lOU1RBTExfRElSfS9rdWJlX2Vudi55YW1sIC0tdj04ICApCn0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKL2Jpbi9zeXN0ZW1kLW1hY2hpbmUtaWQtc2V0dXAgfHwgZWNobyAiZmFpbGVkIHRvIHNldCB1cCBlbnN1cmUgbWFjaGluZS1pZCBjb25maWd1cmVkIgoKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIHN0YXJ0aW5nID09IgplbnN1cmUtaW5zdGFsbC1kaXIKCmNhdCA+IGt1YmVfZW52LnlhbWwgPDwgX19FT0ZfS1VCRV9FTlYKQXNzZXRzOgotIDdkNzBlMDkwOTUxNDg2Y2FlNTJkOWE4MmI3YWFmNTA1NmY4NGY4ZWRAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9yZWxlYXNlL3YxLjQuNi9iaW4vbGludXgvYW1kNjQva3ViZWxldAotIDlhZGNkMTIwZmRiN2FkNmU2NGMwNjFlNTZhMDVmZWZjMTJlOTYxOGJAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9yZWxlYXNlL3YxLjQuNi9iaW4vbGludXgvYW1kNjQva3ViZWN0bAotIDE5ZDQ5ZjdiMmI5OWNkMjQ5M2Q1YWUwYWNlODk2YzY0ZTI4OWNjYmJAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9uZXR3b3JrLXBsdWdpbnMvY25pLTA3YThhMjg2MzdlOTdiMjJlYjhkZmU3MTBlZWFlMTM0NGY2OWQxNmUudGFyLmd6Ci0gY2JiYTg1Njc0NmE0NDFjN2QxYTllOTVlMTQxYzk4MmExYjg4NjRlNkBodHRwczovL2t1YmV1cHYyLnMzLmFtYXpvbmF3cy5jb20va29wcy8xLjUuMC9saW51eC9hbWQ2NC91dGlscy50YXIuZ3oKQ2x1c3Rlck5hbWU6IG1pbmltYWwuZXhhbXBsZS5jb20KQ29uZmlnQmFzZTogbWVtZnM6Ly9jbHVzdGVycy5leGFtcGxlLmNvbS9taW5pbWFsLmV4YW1wbGUuY29tCkluc3RhbmNlR3JvdXBOYW1lOiBtYXN0ZXItdXMtdGVzdC0xYQpUYWdzOgotIF9hdXRvbWF0aWNfdXBncmFkZXMKLSBfYXdzCi0gX2t1YmVybmV0ZXNfbWFzdGVyCmNoYW5uZWxzOgotIG1lbWZzOi8vY2x1c3RlcnMuZXhhbXBsZS5jb20vbWluaW1hbC5leGFtcGxlLmNvbS9hZGRvbnMvYm9vdHN0cmFwLWNoYW5uZWwueWFtbApwcm90b2t1YmVJbWFnZToKICBoYXNoOiA3YzNhMGVjMDcyM2ZkMzUwNjA5YjI5NThiYzViOGFiMDI1ODM4NTFjCiAgbmFtZTogcHJvdG9rdWJlOjEuNS4wCiAgc291cmNlOiBodHRwczovL2t1YmV1cHYyLnMzLmFtYXpvbmF3cy5jb20va29wcy8xLjUuMC9pbWFnZXMvcHJvdG9rdWJlLnRhci5negoKX19FT0ZfS1VCRV9FTlYKCmRvd25sb2FkLXJlbGVhc2UKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIGRvbmUgPT0iCg==" + "UserData": "IyEvYmluL2Jhc2gKIyBDb3B5cmlnaHQgMjAxNiBUaGUgS3ViZXJuZXRlcyBBdXRob3JzIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiMKIyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKIyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiMgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiMKIyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiMKIyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKIyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KIyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiMgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgpzZXQgLW8gZXJyZXhpdApzZXQgLW8gbm91bnNldApzZXQgLW8gcGlwZWZhaWwKCk5PREVVUF9VUkw9aHR0cHM6Ly9rdWJldXB2Mi5zMy5hbWF6b25hd3MuY29tL2tvcHMvMS41LjAvbGludXgvYW1kNjQvbm9kZXVwCk5PREVVUF9IQVNIPQoKCgoKCgpmdW5jdGlvbiBlbnN1cmUtaW5zdGFsbC1kaXIoKSB7CiAgSU5TVEFMTF9ESVI9Ii92YXIvY2FjaGUva3ViZXJuZXRlcy1pbnN0YWxsIgogICMgT24gQ29udGFpbmVyT1MsIHdlIGluc3RhbGwgdG8gL3Zhci9saWIvdG9vbGJveCBpbnN0YWxsIChiZWNhdXNlIG9mIG5vZXhlYykKICBpZiBbWyAtZCAvdmFyL2xpYi90b29sYm94IF1dOyB0aGVuCiAgICBJTlNUQUxMX0RJUj0iL3Zhci9saWIvdG9vbGJveC9rdWJlcm5ldGVzLWluc3RhbGwiCiAgZmkKICBta2RpciAtcCAke0lOU1RBTExfRElSfQogIGNkICR7SU5TVEFMTF9ESVJ9Cn0KCiMgUmV0cnkgYSBkb3dubG9hZCB1bnRpbCB3ZSBnZXQgaXQuIFRha2VzIGEgaGFzaCBhbmQgYSBzZXQgb2YgVVJMcy4KIwojICQxIGlzIHRoZSBzaGExIG9mIHRoZSBVUkwuIENhbiBiZSAiIiBpZiB0aGUgc2hhMSBpcyB1bmtub3duLgojICQyKyBhcmUgdGhlIFVSTHMgdG8gZG93bmxvYWQuCmRvd25sb2FkLW9yLWJ1c3QoKSB7CiAgbG9jYWwgLXIgaGFzaD0iJDEiCiAgc2hpZnQgMQoKICB1cmxzPSggJCogKQogIHdoaWxlIHRydWU7IGRvCiAgICBmb3IgdXJsIGluICIke3VybHNbQF19IjsgZG8KICAgICAgbG9jYWwgZmlsZT0iJHt1cmwjIyovfSIKICAgICAgcm0gLWYgIiR7ZmlsZX0iCiAgICAgIGlmICEgY3VybCAtZiAtLWlwdjQgLUxvICIke2ZpbGV9IiAtLWNvbm5lY3QtdGltZW91dCAyMCAtLXJldHJ5IDYgLS1yZXRyeS1kZWxheSAxMCAiJHt1cmx9IjsgdGhlbgogICAgICAgIGVjaG8gIj09IEZhaWxlZCB0byBkb3dubG9hZCAke3VybH0uIFJldHJ5aW5nLiA9PSIKICAgICAgZWxpZiBbWyAtbiAiJHtoYXNofSIgXV0gJiYgISB2YWxpZGF0ZS1oYXNoICIke2ZpbGV9IiAiJHtoYXNofSI7IHRoZW4KICAgICAgICBlY2hvICI9PSBIYXNoIHZhbGlkYXRpb24gb2YgJHt1cmx9IGZhaWxlZC4gUmV0cnlpbmcuID09IgogICAgICBlbHNlCiAgICAgICAgaWYgW1sgLW4gIiR7aGFzaH0iIF1dOyB0aGVuCiAgICAgICAgICBlY2hvICI9PSBEb3dubG9hZGVkICR7dXJsfSAoU0hBMSA9ICR7aGFzaH0pID09IgogICAgICAgIGVsc2UKICAgICAgICAgIGVjaG8gIj09IERvd25sb2FkZWQgJHt1cmx9ID09IgogICAgICAgIGZpCiAgICAgICAgcmV0dXJuCiAgICAgIGZpCiAgICBkb25lCgogICAgZWNobyAiQWxsIGRvd25sb2FkcyBmYWlsZWQ7IHNsZWVwaW5nIGJlZm9yZSByZXRyeWluZyIKICAgIHNsZWVwIDYwCiAgZG9uZQp9Cgp2YWxpZGF0ZS1oYXNoKCkgewogIGxvY2FsIC1yIGZpbGU9IiQxIgogIGxvY2FsIC1yIGV4cGVjdGVkPSIkMiIKICBsb2NhbCBhY3R1YWwKCiAgYWN0dWFsPSQoc2hhMXN1bSAke2ZpbGV9IHwgYXdrICd7IHByaW50ICQxIH0nKSB8fCB0cnVlCiAgaWYgW1sgIiR7YWN0dWFsfSIgIT0gIiR7ZXhwZWN0ZWR9IiBdXTsgdGhlbgogICAgZWNobyAiPT0gJHtmaWxlfSBjb3JydXB0ZWQsIHNoYTEgJHthY3R1YWx9IGRvZXNuJ3QgbWF0Y2ggZXhwZWN0ZWQgJHtleHBlY3RlZH0gPT0iCiAgICByZXR1cm4gMQogIGZpCn0KCmZ1bmN0aW9uIHNwbGl0LWNvbW1hcygpIHsKICBlY2hvICQxIHwgdHIgIiwiICJcbiIKfQoKZnVuY3Rpb24gdHJ5LWRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBUT0RPKHptZXJseW5uKTogTm93IHdlIFJFQUxMWSBoYXZlIG5vIGV4Y3VzZSBub3QgdG8gZG8gdGhlIHJlYm9vdAogICMgb3B0aW1pemF0aW9uLgoKICBsb2NhbCAtciBub2RldXBfdXJscz0oICQoc3BsaXQtY29tbWFzICIke05PREVVUF9VUkx9IikgKQogIGxvY2FsIC1yIG5vZGV1cF9maWxlbmFtZT0iJHtub2RldXBfdXJsc1swXSMjKi99IgogIGlmIFtbIC1uICIke05PREVVUF9IQVNIOi19IiBdXTsgdGhlbgogICAgbG9jYWwgLXIgbm9kZXVwX2hhc2g9IiR7Tk9ERVVQX0hBU0h9IgogIGVsc2UKICAjIFRPRE86IFJlbW92ZT8KICAgIGVjaG8gIkRvd25sb2FkaW5nIHNoYTEgKG5vdCBmb3VuZCBpbiBlbnYpIgogICAgZG93bmxvYWQtb3ItYnVzdCAiIiAiJHtub2RldXBfdXJsc1tAXS8lLy5zaGExfSIKICAgIGxvY2FsIC1yIG5vZGV1cF9oYXNoPSQoY2F0ICIke25vZGV1cF9maWxlbmFtZX0uc2hhMSIpCiAgZmkKCiAgZWNobyAiRG93bmxvYWRpbmcgbm9kZXVwICgke25vZGV1cF91cmxzW0BdfSkiCiAgZG93bmxvYWQtb3ItYnVzdCAiJHtub2RldXBfaGFzaH0iICIke25vZGV1cF91cmxzW0BdfSIKCiAgY2htb2QgK3ggbm9kZXVwCn0KCmZ1bmN0aW9uIGRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBJbiBjYXNlIG9mIGZhaWx1cmUgY2hlY2tpbmcgaW50ZWdyaXR5IG9mIHJlbGVhc2UsIHJldHJ5LgogIHVudGlsIHRyeS1kb3dubG9hZC1yZWxlYXNlOyBkbwogICAgc2xlZXAgMTUKICAgIGVjaG8gIkNvdWxkbid0IGRvd25sb2FkIHJlbGVhc2UuIFJldHJ5aW5nLi4uIgogIGRvbmUKCiAgZWNobyAiUnVubmluZyBub2RldXAiCiAgIyBXZSBjYW4ndCBydW4gaW4gdGhlIGZvcmVncm91bmQgYmVjYXVzZSBvZiBodHRwczovL2dpdGh1Yi5jb20vZG9ja2VyL2RvY2tlci9pc3N1ZXMvMjM3OTMKICAoIGNkICR7SU5TVEFMTF9ESVJ9OyAuL25vZGV1cCAtLWluc3RhbGwtc3lzdGVtZC11bml0IC0tY29uZj0ke0lOU1RBTExfRElSfS9rdWJlX2Vudi55YW1sIC0tdj04ICApCn0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKL2Jpbi9zeXN0ZW1kLW1hY2hpbmUtaWQtc2V0dXAgfHwgZWNobyAiZmFpbGVkIHRvIHNldCB1cCBlbnN1cmUgbWFjaGluZS1pZCBjb25maWd1cmVkIgoKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIHN0YXJ0aW5nID09IgplbnN1cmUtaW5zdGFsbC1kaXIKCmNhdCA+IGNsdXN0ZXJfc3BlYy55YW1sIDw8IF9fRU9GX0NMVVNURVJfU1BFQwpjbG91ZENvbmZpZzogbnVsbApkb2NrZXI6CiAgYnJpZGdlOiAiIgogIGlwTWFzcTogZmFsc2UKICBpcFRhYmxlczogZmFsc2UKICBsb2dMZXZlbDogd2FybgogIHN0b3JhZ2U6IG92ZXJsYXksYXVmcwogIHZlcnNpb246IDEuMTEuMgprdWJlQVBJU2VydmVyOgogIGFkZHJlc3M6IDEyNy4wLjAuMQogIGFkbWlzc2lvbkNvbnRyb2w6CiAgLSBOYW1lc3BhY2VMaWZlY3ljbGUKICAtIExpbWl0UmFuZ2VyCiAgLSBTZXJ2aWNlQWNjb3VudAogIC0gUGVyc2lzdGVudFZvbHVtZUxhYmVsCiAgLSBEZWZhdWx0U3RvcmFnZUNsYXNzCiAgLSBSZXNvdXJjZVF1b3RhCiAgYWxsb3dQcml2aWxlZ2VkOiB0cnVlCiAgYXBpU2VydmVyQ291bnQ6IDEKICBhdXRob3JpemF0aW9uTW9kZTogQWx3YXlzQWxsb3cKICBjbG91ZFByb3ZpZGVyOiBhd3MKICBldGNkU2VydmVyczoKICAtIGh0dHA6Ly8xMjcuMC4wLjE6NDAwMQogIGV0Y2RTZXJ2ZXJzT3ZlcnJpZGVzOgogIC0gL2V2ZW50cyNodHRwOi8vMTI3LjAuMC4xOjQwMDIKICBpbWFnZTogZ2NyLmlvL2dvb2dsZV9jb250YWluZXJzL2t1YmUtYXBpc2VydmVyOnYxLjQuNgogIGluc2VjdXJlUG9ydDogODA4MAogIGxvZ0xldmVsOiAyCiAgc2VjdXJlUG9ydDogNDQzCiAgc2VydmljZUNsdXN0ZXJJUFJhbmdlOiAxMDAuNjQuMC4wLzEzCiAgc3RvcmFnZUJhY2tlbmQ6IGV0Y2QyCmt1YmVDb250cm9sbGVyTWFuYWdlcjoKICBhbGxvY2F0ZU5vZGVDSURSczogdHJ1ZQogIGNsb3VkUHJvdmlkZXI6IGF3cwogIGNsdXN0ZXJDSURSOiAxMDAuOTYuMC4wLzExCiAgY2x1c3Rlck5hbWU6IG1pbmltYWwuZXhhbXBsZS5jb20KICBjb25maWd1cmVDbG91ZFJvdXRlczogdHJ1ZQogIGltYWdlOiBnY3IuaW8vZ29vZ2xlX2NvbnRhaW5lcnMva3ViZS1jb250cm9sbGVyLW1hbmFnZXI6djEuNC42CiAgbGVhZGVyRWxlY3Rpb246CiAgICBsZWFkZXJFbGVjdDogdHJ1ZQogIGxvZ0xldmVsOiAyCiAgbWFzdGVyOiAxMjcuMC4wLjE6ODA4MAprdWJlUHJveHk6CiAgY2x1c3RlckNJRFI6IDEwMC45Ni4wLjAvMTEKICBjcHVSZXF1ZXN0OiAxMDBtCiAgZmVhdHVyZUdhdGVzOiBudWxsCiAgaG9zdG5hbWVPdmVycmlkZTogJ0Bhd3MnCiAgaW1hZ2U6IGdjci5pby9nb29nbGVfY29udGFpbmVycy9rdWJlLXByb3h5OnYxLjQuNgogIGxvZ0xldmVsOiAyCmt1YmVTY2hlZHVsZXI6CiAgaW1hZ2U6IGdjci5pby9nb29nbGVfY29udGFpbmVycy9rdWJlLXNjaGVkdWxlcjp2MS40LjYKICBsZWFkZXJFbGVjdGlvbjoKICAgIGxlYWRlckVsZWN0OiB0cnVlCiAgbG9nTGV2ZWw6IDIKICBtYXN0ZXI6IGh0dHA6Ly8xMjcuMC4wLjE6ODA4MAprdWJlbGV0OgogIGFsbG93UHJpdmlsZWdlZDogdHJ1ZQogIGFwaVNlcnZlcnM6IGh0dHBzOi8vYXBpLmludGVybmFsLm1pbmltYWwuZXhhbXBsZS5jb20KICBiYWJ5c2l0RGFlbW9uczogdHJ1ZQogIGNncm91cFJvb3Q6IGRvY2tlcgogIGNsb3VkUHJvdmlkZXI6IGF3cwogIGNsdXN0ZXJETlM6IDEwMC42NC4wLjEwCiAgY2x1c3RlckRvbWFpbjogY2x1c3Rlci5sb2NhbAogIGVuYWJsZURlYnVnZ2luZ0hhbmRsZXJzOiB0cnVlCiAgZXZpY3Rpb25IYXJkOiBtZW1vcnkuYXZhaWxhYmxlPDEwME1pLG5vZGVmcy5hdmFpbGFibGU8MTAlLG5vZGVmcy5pbm9kZXNGcmVlPDUlLGltYWdlZnMuYXZhaWxhYmxlPDEwJSxpbWFnZWZzLmlub2Rlc0ZyZWU8NSUKICBob3N0bmFtZU92ZXJyaWRlOiAnQGF3cycKICBsb2dMZXZlbDogMgogIG5ldHdvcmtQbHVnaW5NVFU6IDkwMDEKICBuZXR3b3JrUGx1Z2luTmFtZToga3ViZW5ldAogIG5vbk1hc3F1ZXJhZGVDSURSOiAxMDAuNjQuMC4wLzEwCiAgcG9kSW5mcmFDb250YWluZXJJbWFnZTogZ2NyLmlvL2dvb2dsZV9jb250YWluZXJzL3BhdXNlLWFtZDY0OjMuMAogIHBvZE1hbmlmZXN0UGF0aDogL2V0Yy9rdWJlcm5ldGVzL21hbmlmZXN0cwogIHJlY29uY2lsZUNJRFI6IHRydWUKbWFzdGVyS3ViZWxldDoKICBhbGxvd1ByaXZpbGVnZWQ6IHRydWUKICBhcGlTZXJ2ZXJzOiBodHRwOi8vMTI3LjAuMC4xOjgwODAKICBiYWJ5c2l0RGFlbW9uczogdHJ1ZQogIGNncm91cFJvb3Q6IGRvY2tlcgogIGNsb3VkUHJvdmlkZXI6IGF3cwogIGNsdXN0ZXJETlM6IDEwMC42NC4wLjEwCiAgY2x1c3RlckRvbWFpbjogY2x1c3Rlci5sb2NhbAogIGVuYWJsZURlYnVnZ2luZ0hhbmRsZXJzOiB0cnVlCiAgZXZpY3Rpb25IYXJkOiBtZW1vcnkuYXZhaWxhYmxlPDEwME1pLG5vZGVmcy5hdmFpbGFibGU8MTAlLG5vZGVmcy5pbm9kZXNGcmVlPDUlLGltYWdlZnMuYXZhaWxhYmxlPDEwJSxpbWFnZWZzLmlub2Rlc0ZyZWU8NSUKICBob3N0bmFtZU92ZXJyaWRlOiAnQGF3cycKICBsb2dMZXZlbDogMgogIG5ldHdvcmtQbHVnaW5NVFU6IDkwMDEKICBuZXR3b3JrUGx1Z2luTmFtZToga3ViZW5ldAogIG5vbk1hc3F1ZXJhZGVDSURSOiAxMDAuNjQuMC4wLzEwCiAgcG9kQ0lEUjogMTAuMTIzLjQ1LjAvMjgKICBwb2RJbmZyYUNvbnRhaW5lckltYWdlOiBnY3IuaW8vZ29vZ2xlX2NvbnRhaW5lcnMvcGF1c2UtYW1kNjQ6My4wCiAgcG9kTWFuaWZlc3RQYXRoOiAvZXRjL2t1YmVybmV0ZXMvbWFuaWZlc3RzCiAgcmVjb25jaWxlQ0lEUjogdHJ1ZQogIHJlZ2lzdGVyU2NoZWR1bGFibGU6IGZhbHNlCgpfX0VPRl9DTFVTVEVSX1NQRUMKCmNhdCA+IGlnX3NwZWMueWFtbCA8PCBfX0VPRl9JR19TUEVDCmt1YmVsZXQ6IG51bGwKbm9kZUxhYmVsczogbnVsbAp0YWludHM6IG51bGwKCl9fRU9GX0lHX1NQRUMKCmNhdCA+IGt1YmVfZW52LnlhbWwgPDwgX19FT0ZfS1VCRV9FTlYKQXNzZXRzOgotIDdkNzBlMDkwOTUxNDg2Y2FlNTJkOWE4MmI3YWFmNTA1NmY4NGY4ZWRAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9yZWxlYXNlL3YxLjQuNi9iaW4vbGludXgvYW1kNjQva3ViZWxldAotIDlhZGNkMTIwZmRiN2FkNmU2NGMwNjFlNTZhMDVmZWZjMTJlOTYxOGJAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9yZWxlYXNlL3YxLjQuNi9iaW4vbGludXgvYW1kNjQva3ViZWN0bAotIDE5ZDQ5ZjdiMmI5OWNkMjQ5M2Q1YWUwYWNlODk2YzY0ZTI4OWNjYmJAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9uZXR3b3JrLXBsdWdpbnMvY25pLTA3YThhMjg2MzdlOTdiMjJlYjhkZmU3MTBlZWFlMTM0NGY2OWQxNmUudGFyLmd6Ci0gY2JiYTg1Njc0NmE0NDFjN2QxYTllOTVlMTQxYzk4MmExYjg4NjRlNkBodHRwczovL2t1YmV1cHYyLnMzLmFtYXpvbmF3cy5jb20va29wcy8xLjUuMC9saW51eC9hbWQ2NC91dGlscy50YXIuZ3oKQ2x1c3Rlck5hbWU6IG1pbmltYWwuZXhhbXBsZS5jb20KQ29uZmlnQmFzZTogbWVtZnM6Ly9jbHVzdGVycy5leGFtcGxlLmNvbS9taW5pbWFsLmV4YW1wbGUuY29tCkluc3RhbmNlR3JvdXBOYW1lOiBtYXN0ZXItdXMtdGVzdC0xYQpUYWdzOgotIF9hdXRvbWF0aWNfdXBncmFkZXMKLSBfYXdzCi0gX2t1YmVybmV0ZXNfbWFzdGVyCmNoYW5uZWxzOgotIG1lbWZzOi8vY2x1c3RlcnMuZXhhbXBsZS5jb20vbWluaW1hbC5leGFtcGxlLmNvbS9hZGRvbnMvYm9vdHN0cmFwLWNoYW5uZWwueWFtbApwcm90b2t1YmVJbWFnZToKICBoYXNoOiA3YzNhMGVjMDcyM2ZkMzUwNjA5YjI5NThiYzViOGFiMDI1ODM4NTFjCiAgbmFtZTogcHJvdG9rdWJlOjEuNS4wCiAgc291cmNlOiBodHRwczovL2t1YmV1cHYyLnMzLmFtYXpvbmF3cy5jb20va29wcy8xLjUuMC9pbWFnZXMvcHJvdG9rdWJlLnRhci5negoKX19FT0ZfS1VCRV9FTlYKCmRvd25sb2FkLXJlbGVhc2UKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIGRvbmUgPT0iCg==" } }, "AWSAutoScalingLaunchConfigurationnodesminimalexamplecom": { @@ -121,7 +121,7 @@ "Ref": "AWSEC2SecurityGroupnodesminimalexamplecom" } ], - "UserData": "IyEvYmluL2Jhc2gKIyBDb3B5cmlnaHQgMjAxNiBUaGUgS3ViZXJuZXRlcyBBdXRob3JzIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiMKIyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKIyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiMgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiMKIyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiMKIyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKIyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KIyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiMgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgpzZXQgLW8gZXJyZXhpdApzZXQgLW8gbm91bnNldApzZXQgLW8gcGlwZWZhaWwKCk5PREVVUF9VUkw9aHR0cHM6Ly9rdWJldXB2Mi5zMy5hbWF6b25hd3MuY29tL2tvcHMvMS41LjAvbGludXgvYW1kNjQvbm9kZXVwCk5PREVVUF9IQVNIPQoKCgoKCgpmdW5jdGlvbiBlbnN1cmUtaW5zdGFsbC1kaXIoKSB7CiAgSU5TVEFMTF9ESVI9Ii92YXIvY2FjaGUva3ViZXJuZXRlcy1pbnN0YWxsIgogICMgT24gQ29udGFpbmVyT1MsIHdlIGluc3RhbGwgdG8gL3Zhci9saWIvdG9vbGJveCBpbnN0YWxsIChiZWNhdXNlIG9mIG5vZXhlYykKICBpZiBbWyAtZCAvdmFyL2xpYi90b29sYm94IF1dOyB0aGVuCiAgICBJTlNUQUxMX0RJUj0iL3Zhci9saWIvdG9vbGJveC9rdWJlcm5ldGVzLWluc3RhbGwiCiAgZmkKICBta2RpciAtcCAke0lOU1RBTExfRElSfQogIGNkICR7SU5TVEFMTF9ESVJ9Cn0KCiMgUmV0cnkgYSBkb3dubG9hZCB1bnRpbCB3ZSBnZXQgaXQuIFRha2VzIGEgaGFzaCBhbmQgYSBzZXQgb2YgVVJMcy4KIwojICQxIGlzIHRoZSBzaGExIG9mIHRoZSBVUkwuIENhbiBiZSAiIiBpZiB0aGUgc2hhMSBpcyB1bmtub3duLgojICQyKyBhcmUgdGhlIFVSTHMgdG8gZG93bmxvYWQuCmRvd25sb2FkLW9yLWJ1c3QoKSB7CiAgbG9jYWwgLXIgaGFzaD0iJDEiCiAgc2hpZnQgMQoKICB1cmxzPSggJCogKQogIHdoaWxlIHRydWU7IGRvCiAgICBmb3IgdXJsIGluICIke3VybHNbQF19IjsgZG8KICAgICAgbG9jYWwgZmlsZT0iJHt1cmwjIyovfSIKICAgICAgcm0gLWYgIiR7ZmlsZX0iCiAgICAgIGlmICEgY3VybCAtZiAtLWlwdjQgLUxvICIke2ZpbGV9IiAtLWNvbm5lY3QtdGltZW91dCAyMCAtLXJldHJ5IDYgLS1yZXRyeS1kZWxheSAxMCAiJHt1cmx9IjsgdGhlbgogICAgICAgIGVjaG8gIj09IEZhaWxlZCB0byBkb3dubG9hZCAke3VybH0uIFJldHJ5aW5nLiA9PSIKICAgICAgZWxpZiBbWyAtbiAiJHtoYXNofSIgXV0gJiYgISB2YWxpZGF0ZS1oYXNoICIke2ZpbGV9IiAiJHtoYXNofSI7IHRoZW4KICAgICAgICBlY2hvICI9PSBIYXNoIHZhbGlkYXRpb24gb2YgJHt1cmx9IGZhaWxlZC4gUmV0cnlpbmcuID09IgogICAgICBlbHNlCiAgICAgICAgaWYgW1sgLW4gIiR7aGFzaH0iIF1dOyB0aGVuCiAgICAgICAgICBlY2hvICI9PSBEb3dubG9hZGVkICR7dXJsfSAoU0hBMSA9ICR7aGFzaH0pID09IgogICAgICAgIGVsc2UKICAgICAgICAgIGVjaG8gIj09IERvd25sb2FkZWQgJHt1cmx9ID09IgogICAgICAgIGZpCiAgICAgICAgcmV0dXJuCiAgICAgIGZpCiAgICBkb25lCgogICAgZWNobyAiQWxsIGRvd25sb2FkcyBmYWlsZWQ7IHNsZWVwaW5nIGJlZm9yZSByZXRyeWluZyIKICAgIHNsZWVwIDYwCiAgZG9uZQp9Cgp2YWxpZGF0ZS1oYXNoKCkgewogIGxvY2FsIC1yIGZpbGU9IiQxIgogIGxvY2FsIC1yIGV4cGVjdGVkPSIkMiIKICBsb2NhbCBhY3R1YWwKCiAgYWN0dWFsPSQoc2hhMXN1bSAke2ZpbGV9IHwgYXdrICd7IHByaW50ICQxIH0nKSB8fCB0cnVlCiAgaWYgW1sgIiR7YWN0dWFsfSIgIT0gIiR7ZXhwZWN0ZWR9IiBdXTsgdGhlbgogICAgZWNobyAiPT0gJHtmaWxlfSBjb3JydXB0ZWQsIHNoYTEgJHthY3R1YWx9IGRvZXNuJ3QgbWF0Y2ggZXhwZWN0ZWQgJHtleHBlY3RlZH0gPT0iCiAgICByZXR1cm4gMQogIGZpCn0KCmZ1bmN0aW9uIHNwbGl0LWNvbW1hcygpIHsKICBlY2hvICQxIHwgdHIgIiwiICJcbiIKfQoKZnVuY3Rpb24gdHJ5LWRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBUT0RPKHptZXJseW5uKTogTm93IHdlIFJFQUxMWSBoYXZlIG5vIGV4Y3VzZSBub3QgdG8gZG8gdGhlIHJlYm9vdAogICMgb3B0aW1pemF0aW9uLgoKICBsb2NhbCAtciBub2RldXBfdXJscz0oICQoc3BsaXQtY29tbWFzICIke05PREVVUF9VUkx9IikgKQogIGxvY2FsIC1yIG5vZGV1cF9maWxlbmFtZT0iJHtub2RldXBfdXJsc1swXSMjKi99IgogIGlmIFtbIC1uICIke05PREVVUF9IQVNIOi19IiBdXTsgdGhlbgogICAgbG9jYWwgLXIgbm9kZXVwX2hhc2g9IiR7Tk9ERVVQX0hBU0h9IgogIGVsc2UKICAjIFRPRE86IFJlbW92ZT8KICAgIGVjaG8gIkRvd25sb2FkaW5nIHNoYTEgKG5vdCBmb3VuZCBpbiBlbnYpIgogICAgZG93bmxvYWQtb3ItYnVzdCAiIiAiJHtub2RldXBfdXJsc1tAXS8lLy5zaGExfSIKICAgIGxvY2FsIC1yIG5vZGV1cF9oYXNoPSQoY2F0ICIke25vZGV1cF9maWxlbmFtZX0uc2hhMSIpCiAgZmkKCiAgZWNobyAiRG93bmxvYWRpbmcgbm9kZXVwICgke25vZGV1cF91cmxzW0BdfSkiCiAgZG93bmxvYWQtb3ItYnVzdCAiJHtub2RldXBfaGFzaH0iICIke25vZGV1cF91cmxzW0BdfSIKCiAgY2htb2QgK3ggbm9kZXVwCn0KCmZ1bmN0aW9uIGRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBJbiBjYXNlIG9mIGZhaWx1cmUgY2hlY2tpbmcgaW50ZWdyaXR5IG9mIHJlbGVhc2UsIHJldHJ5LgogIHVudGlsIHRyeS1kb3dubG9hZC1yZWxlYXNlOyBkbwogICAgc2xlZXAgMTUKICAgIGVjaG8gIkNvdWxkbid0IGRvd25sb2FkIHJlbGVhc2UuIFJldHJ5aW5nLi4uIgogIGRvbmUKCiAgZWNobyAiUnVubmluZyBub2RldXAiCiAgIyBXZSBjYW4ndCBydW4gaW4gdGhlIGZvcmVncm91bmQgYmVjYXVzZSBvZiBodHRwczovL2dpdGh1Yi5jb20vZG9ja2VyL2RvY2tlci9pc3N1ZXMvMjM3OTMKICAoIGNkICR7SU5TVEFMTF9ESVJ9OyAuL25vZGV1cCAtLWluc3RhbGwtc3lzdGVtZC11bml0IC0tY29uZj0ke0lOU1RBTExfRElSfS9rdWJlX2Vudi55YW1sIC0tdj04ICApCn0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKL2Jpbi9zeXN0ZW1kLW1hY2hpbmUtaWQtc2V0dXAgfHwgZWNobyAiZmFpbGVkIHRvIHNldCB1cCBlbnN1cmUgbWFjaGluZS1pZCBjb25maWd1cmVkIgoKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIHN0YXJ0aW5nID09IgplbnN1cmUtaW5zdGFsbC1kaXIKCmNhdCA+IGt1YmVfZW52LnlhbWwgPDwgX19FT0ZfS1VCRV9FTlYKQXNzZXRzOgotIDdkNzBlMDkwOTUxNDg2Y2FlNTJkOWE4MmI3YWFmNTA1NmY4NGY4ZWRAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9yZWxlYXNlL3YxLjQuNi9iaW4vbGludXgvYW1kNjQva3ViZWxldAotIDlhZGNkMTIwZmRiN2FkNmU2NGMwNjFlNTZhMDVmZWZjMTJlOTYxOGJAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9yZWxlYXNlL3YxLjQuNi9iaW4vbGludXgvYW1kNjQva3ViZWN0bAotIDE5ZDQ5ZjdiMmI5OWNkMjQ5M2Q1YWUwYWNlODk2YzY0ZTI4OWNjYmJAaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2t1YmVybmV0ZXMtcmVsZWFzZS9uZXR3b3JrLXBsdWdpbnMvY25pLTA3YThhMjg2MzdlOTdiMjJlYjhkZmU3MTBlZWFlMTM0NGY2OWQxNmUudGFyLmd6Ci0gY2JiYTg1Njc0NmE0NDFjN2QxYTllOTVlMTQxYzk4MmExYjg4NjRlNkBodHRwczovL2t1YmV1cHYyLnMzLmFtYXpvbmF3cy5jb20va29wcy8xLjUuMC9saW51eC9hbWQ2NC91dGlscy50YXIuZ3oKQ2x1c3Rlck5hbWU6IG1pbmltYWwuZXhhbXBsZS5jb20KQ29uZmlnQmFzZTogbWVtZnM6Ly9jbHVzdGVycy5leGFtcGxlLmNvbS9taW5pbWFsLmV4YW1wbGUuY29tCkluc3RhbmNlR3JvdXBOYW1lOiBub2RlcwpUYWdzOgotIF9hdXRvbWF0aWNfdXBncmFkZXMKLSBfYXdzCmNoYW5uZWxzOgotIG1lbWZzOi8vY2x1c3RlcnMuZXhhbXBsZS5jb20vbWluaW1hbC5leGFtcGxlLmNvbS9hZGRvbnMvYm9vdHN0cmFwLWNoYW5uZWwueWFtbApwcm90b2t1YmVJbWFnZToKICBoYXNoOiA3YzNhMGVjMDcyM2ZkMzUwNjA5YjI5NThiYzViOGFiMDI1ODM4NTFjCiAgbmFtZTogcHJvdG9rdWJlOjEuNS4wCiAgc291cmNlOiBodHRwczovL2t1YmV1cHYyLnMzLmFtYXpvbmF3cy5jb20va29wcy8xLjUuMC9pbWFnZXMvcHJvdG9rdWJlLnRhci5negoKX19FT0ZfS1VCRV9FTlYKCmRvd25sb2FkLXJlbGVhc2UKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIGRvbmUgPT0iCg==" + "UserData": "IyEvYmluL2Jhc2gKIyBDb3B5cmlnaHQgMjAxNiBUaGUgS3ViZXJuZXRlcyBBdXRob3JzIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiMKIyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKIyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiMgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiMKIyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiMKIyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKIyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KIyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiMgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgpzZXQgLW8gZXJyZXhpdApzZXQgLW8gbm91bnNldApzZXQgLW8gcGlwZWZhaWwKCk5PREVVUF9VUkw9aHR0cHM6Ly9rdWJldXB2Mi5zMy5hbWF6b25hd3MuY29tL2tvcHMvMS41LjAvbGludXgvYW1kNjQvbm9kZXVwCk5PREVVUF9IQVNIPQoKCgoKCgpmdW5jdGlvbiBlbnN1cmUtaW5zdGFsbC1kaXIoKSB7CiAgSU5TVEFMTF9ESVI9Ii92YXIvY2FjaGUva3ViZXJuZXRlcy1pbnN0YWxsIgogICMgT24gQ29udGFpbmVyT1MsIHdlIGluc3RhbGwgdG8gL3Zhci9saWIvdG9vbGJveCBpbnN0YWxsIChiZWNhdXNlIG9mIG5vZXhlYykKICBpZiBbWyAtZCAvdmFyL2xpYi90b29sYm94IF1dOyB0aGVuCiAgICBJTlNUQUxMX0RJUj0iL3Zhci9saWIvdG9vbGJveC9rdWJlcm5ldGVzLWluc3RhbGwiCiAgZmkKICBta2RpciAtcCAke0lOU1RBTExfRElSfQogIGNkICR7SU5TVEFMTF9ESVJ9Cn0KCiMgUmV0cnkgYSBkb3dubG9hZCB1bnRpbCB3ZSBnZXQgaXQuIFRha2VzIGEgaGFzaCBhbmQgYSBzZXQgb2YgVVJMcy4KIwojICQxIGlzIHRoZSBzaGExIG9mIHRoZSBVUkwuIENhbiBiZSAiIiBpZiB0aGUgc2hhMSBpcyB1bmtub3duLgojICQyKyBhcmUgdGhlIFVSTHMgdG8gZG93bmxvYWQuCmRvd25sb2FkLW9yLWJ1c3QoKSB7CiAgbG9jYWwgLXIgaGFzaD0iJDEiCiAgc2hpZnQgMQoKICB1cmxzPSggJCogKQogIHdoaWxlIHRydWU7IGRvCiAgICBmb3IgdXJsIGluICIke3VybHNbQF19IjsgZG8KICAgICAgbG9jYWwgZmlsZT0iJHt1cmwjIyovfSIKICAgICAgcm0gLWYgIiR7ZmlsZX0iCiAgICAgIGlmICEgY3VybCAtZiAtLWlwdjQgLUxvICIke2ZpbGV9IiAtLWNvbm5lY3QtdGltZW91dCAyMCAtLXJldHJ5IDYgLS1yZXRyeS1kZWxheSAxMCAiJHt1cmx9IjsgdGhlbgogICAgICAgIGVjaG8gIj09IEZhaWxlZCB0byBkb3dubG9hZCAke3VybH0uIFJldHJ5aW5nLiA9PSIKICAgICAgZWxpZiBbWyAtbiAiJHtoYXNofSIgXV0gJiYgISB2YWxpZGF0ZS1oYXNoICIke2ZpbGV9IiAiJHtoYXNofSI7IHRoZW4KICAgICAgICBlY2hvICI9PSBIYXNoIHZhbGlkYXRpb24gb2YgJHt1cmx9IGZhaWxlZC4gUmV0cnlpbmcuID09IgogICAgICBlbHNlCiAgICAgICAgaWYgW1sgLW4gIiR7aGFzaH0iIF1dOyB0aGVuCiAgICAgICAgICBlY2hvICI9PSBEb3dubG9hZGVkICR7dXJsfSAoU0hBMSA9ICR7aGFzaH0pID09IgogICAgICAgIGVsc2UKICAgICAgICAgIGVjaG8gIj09IERvd25sb2FkZWQgJHt1cmx9ID09IgogICAgICAgIGZpCiAgICAgICAgcmV0dXJuCiAgICAgIGZpCiAgICBkb25lCgogICAgZWNobyAiQWxsIGRvd25sb2FkcyBmYWlsZWQ7IHNsZWVwaW5nIGJlZm9yZSByZXRyeWluZyIKICAgIHNsZWVwIDYwCiAgZG9uZQp9Cgp2YWxpZGF0ZS1oYXNoKCkgewogIGxvY2FsIC1yIGZpbGU9IiQxIgogIGxvY2FsIC1yIGV4cGVjdGVkPSIkMiIKICBsb2NhbCBhY3R1YWwKCiAgYWN0dWFsPSQoc2hhMXN1bSAke2ZpbGV9IHwgYXdrICd7IHByaW50ICQxIH0nKSB8fCB0cnVlCiAgaWYgW1sgIiR7YWN0dWFsfSIgIT0gIiR7ZXhwZWN0ZWR9IiBdXTsgdGhlbgogICAgZWNobyAiPT0gJHtmaWxlfSBjb3JydXB0ZWQsIHNoYTEgJHthY3R1YWx9IGRvZXNuJ3QgbWF0Y2ggZXhwZWN0ZWQgJHtleHBlY3RlZH0gPT0iCiAgICByZXR1cm4gMQogIGZpCn0KCmZ1bmN0aW9uIHNwbGl0LWNvbW1hcygpIHsKICBlY2hvICQxIHwgdHIgIiwiICJcbiIKfQoKZnVuY3Rpb24gdHJ5LWRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBUT0RPKHptZXJseW5uKTogTm93IHdlIFJFQUxMWSBoYXZlIG5vIGV4Y3VzZSBub3QgdG8gZG8gdGhlIHJlYm9vdAogICMgb3B0aW1pemF0aW9uLgoKICBsb2NhbCAtciBub2RldXBfdXJscz0oICQoc3BsaXQtY29tbWFzICIke05PREVVUF9VUkx9IikgKQogIGxvY2FsIC1yIG5vZGV1cF9maWxlbmFtZT0iJHtub2RldXBfdXJsc1swXSMjKi99IgogIGlmIFtbIC1uICIke05PREVVUF9IQVNIOi19IiBdXTsgdGhlbgogICAgbG9jYWwgLXIgbm9kZXVwX2hhc2g9IiR7Tk9ERVVQX0hBU0h9IgogIGVsc2UKICAjIFRPRE86IFJlbW92ZT8KICAgIGVjaG8gIkRvd25sb2FkaW5nIHNoYTEgKG5vdCBmb3VuZCBpbiBlbnYpIgogICAgZG93bmxvYWQtb3ItYnVzdCAiIiAiJHtub2RldXBfdXJsc1tAXS8lLy5zaGExfSIKICAgIGxvY2FsIC1yIG5vZGV1cF9oYXNoPSQoY2F0ICIke25vZGV1cF9maWxlbmFtZX0uc2hhMSIpCiAgZmkKCiAgZWNobyAiRG93bmxvYWRpbmcgbm9kZXVwICgke25vZGV1cF91cmxzW0BdfSkiCiAgZG93bmxvYWQtb3ItYnVzdCAiJHtub2RldXBfaGFzaH0iICIke25vZGV1cF91cmxzW0BdfSIKCiAgY2htb2QgK3ggbm9kZXVwCn0KCmZ1bmN0aW9uIGRvd25sb2FkLXJlbGVhc2UoKSB7CiAgIyBJbiBjYXNlIG9mIGZhaWx1cmUgY2hlY2tpbmcgaW50ZWdyaXR5IG9mIHJlbGVhc2UsIHJldHJ5LgogIHVudGlsIHRyeS1kb3dubG9hZC1yZWxlYXNlOyBkbwogICAgc2xlZXAgMTUKICAgIGVjaG8gIkNvdWxkbid0IGRvd25sb2FkIHJlbGVhc2UuIFJldHJ5aW5nLi4uIgogIGRvbmUKCiAgZWNobyAiUnVubmluZyBub2RldXAiCiAgIyBXZSBjYW4ndCBydW4gaW4gdGhlIGZvcmVncm91bmQgYmVjYXVzZSBvZiBodHRwczovL2dpdGh1Yi5jb20vZG9ja2VyL2RvY2tlci9pc3N1ZXMvMjM3OTMKICAoIGNkICR7SU5TVEFMTF9ESVJ9OyAuL25vZGV1cCAtLWluc3RhbGwtc3lzdGVtZC11bml0IC0tY29uZj0ke0lOU1RBTExfRElSfS9rdWJlX2Vudi55YW1sIC0tdj04ICApCn0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKL2Jpbi9zeXN0ZW1kLW1hY2hpbmUtaWQtc2V0dXAgfHwgZWNobyAiZmFpbGVkIHRvIHNldCB1cCBlbnN1cmUgbWFjaGluZS1pZCBjb25maWd1cmVkIgoKZWNobyAiPT0gbm9kZXVwIG5vZGUgY29uZmlnIHN0YXJ0aW5nID09IgplbnN1cmUtaW5zdGFsbC1kaXIKCmNhdCA+IGNsdXN0ZXJfc3BlYy55YW1sIDw8IF9fRU9GX0NMVVNURVJfU1BFQwpjbG91ZENvbmZpZzogbnVsbApkb2NrZXI6CiAgYnJpZGdlOiAiIgogIGlwTWFzcTogZmFsc2UKICBpcFRhYmxlczogZmFsc2UKICBsb2dMZXZlbDogd2FybgogIHN0b3JhZ2U6IG92ZXJsYXksYXVmcwogIHZlcnNpb246IDEuMTEuMgprdWJlUHJveHk6CiAgY2x1c3RlckNJRFI6IDEwMC45Ni4wLjAvMTEKICBjcHVSZXF1ZXN0OiAxMDBtCiAgZmVhdHVyZUdhdGVzOiBudWxsCiAgaG9zdG5hbWVPdmVycmlkZTogJ0Bhd3MnCiAgaW1hZ2U6IGdjci5pby9nb29nbGVfY29udGFpbmVycy9rdWJlLXByb3h5OnYxLjQuNgogIGxvZ0xldmVsOiAyCmt1YmVsZXQ6CiAgYWxsb3dQcml2aWxlZ2VkOiB0cnVlCiAgYXBpU2VydmVyczogaHR0cHM6Ly9hcGkuaW50ZXJuYWwubWluaW1hbC5leGFtcGxlLmNvbQogIGJhYnlzaXREYWVtb25zOiB0cnVlCiAgY2dyb3VwUm9vdDogZG9ja2VyCiAgY2xvdWRQcm92aWRlcjogYXdzCiAgY2x1c3RlckROUzogMTAwLjY0LjAuMTAKICBjbHVzdGVyRG9tYWluOiBjbHVzdGVyLmxvY2FsCiAgZW5hYmxlRGVidWdnaW5nSGFuZGxlcnM6IHRydWUKICBldmljdGlvbkhhcmQ6IG1lbW9yeS5hdmFpbGFibGU8MTAwTWksbm9kZWZzLmF2YWlsYWJsZTwxMCUsbm9kZWZzLmlub2Rlc0ZyZWU8NSUsaW1hZ2Vmcy5hdmFpbGFibGU8MTAlLGltYWdlZnMuaW5vZGVzRnJlZTw1JQogIGhvc3RuYW1lT3ZlcnJpZGU6ICdAYXdzJwogIGxvZ0xldmVsOiAyCiAgbmV0d29ya1BsdWdpbk1UVTogOTAwMQogIG5ldHdvcmtQbHVnaW5OYW1lOiBrdWJlbmV0CiAgbm9uTWFzcXVlcmFkZUNJRFI6IDEwMC42NC4wLjAvMTAKICBwb2RJbmZyYUNvbnRhaW5lckltYWdlOiBnY3IuaW8vZ29vZ2xlX2NvbnRhaW5lcnMvcGF1c2UtYW1kNjQ6My4wCiAgcG9kTWFuaWZlc3RQYXRoOiAvZXRjL2t1YmVybmV0ZXMvbWFuaWZlc3RzCiAgcmVjb25jaWxlQ0lEUjogdHJ1ZQoKX19FT0ZfQ0xVU1RFUl9TUEVDCgpjYXQgPiBpZ19zcGVjLnlhbWwgPDwgX19FT0ZfSUdfU1BFQwprdWJlbGV0OiBudWxsCm5vZGVMYWJlbHM6IG51bGwKdGFpbnRzOiBudWxsCgpfX0VPRl9JR19TUEVDCgpjYXQgPiBrdWJlX2Vudi55YW1sIDw8IF9fRU9GX0tVQkVfRU5WCkFzc2V0czoKLSA3ZDcwZTA5MDk1MTQ4NmNhZTUyZDlhODJiN2FhZjUwNTZmODRmOGVkQGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9rdWJlcm5ldGVzLXJlbGVhc2UvcmVsZWFzZS92MS40LjYvYmluL2xpbnV4L2FtZDY0L2t1YmVsZXQKLSA5YWRjZDEyMGZkYjdhZDZlNjRjMDYxZTU2YTA1ZmVmYzEyZTk2MThiQGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9rdWJlcm5ldGVzLXJlbGVhc2UvcmVsZWFzZS92MS40LjYvYmluL2xpbnV4L2FtZDY0L2t1YmVjdGwKLSAxOWQ0OWY3YjJiOTljZDI0OTNkNWFlMGFjZTg5NmM2NGUyODljY2JiQGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9rdWJlcm5ldGVzLXJlbGVhc2UvbmV0d29yay1wbHVnaW5zL2NuaS0wN2E4YTI4NjM3ZTk3YjIyZWI4ZGZlNzEwZWVhZTEzNDRmNjlkMTZlLnRhci5negotIGNiYmE4NTY3NDZhNDQxYzdkMWE5ZTk1ZTE0MWM5ODJhMWI4ODY0ZTZAaHR0cHM6Ly9rdWJldXB2Mi5zMy5hbWF6b25hd3MuY29tL2tvcHMvMS41LjAvbGludXgvYW1kNjQvdXRpbHMudGFyLmd6CkNsdXN0ZXJOYW1lOiBtaW5pbWFsLmV4YW1wbGUuY29tCkNvbmZpZ0Jhc2U6IG1lbWZzOi8vY2x1c3RlcnMuZXhhbXBsZS5jb20vbWluaW1hbC5leGFtcGxlLmNvbQpJbnN0YW5jZUdyb3VwTmFtZTogbm9kZXMKVGFnczoKLSBfYXV0b21hdGljX3VwZ3JhZGVzCi0gX2F3cwpjaGFubmVsczoKLSBtZW1mczovL2NsdXN0ZXJzLmV4YW1wbGUuY29tL21pbmltYWwuZXhhbXBsZS5jb20vYWRkb25zL2Jvb3RzdHJhcC1jaGFubmVsLnlhbWwKcHJvdG9rdWJlSW1hZ2U6CiAgaGFzaDogN2MzYTBlYzA3MjNmZDM1MDYwOWIyOTU4YmM1YjhhYjAyNTgzODUxYwogIG5hbWU6IHByb3Rva3ViZToxLjUuMAogIHNvdXJjZTogaHR0cHM6Ly9rdWJldXB2Mi5zMy5hbWF6b25hd3MuY29tL2tvcHMvMS41LjAvaW1hZ2VzL3Byb3Rva3ViZS50YXIuZ3oKCl9fRU9GX0tVQkVfRU5WCgpkb3dubG9hZC1yZWxlYXNlCmVjaG8gIj09IG5vZGV1cCBub2RlIGNvbmZpZyBkb25lID09Igo=" } }, "AWSEC2DHCPOptionsminimalexamplecom": { @@ -719,4 +719,4 @@ } } } -} \ No newline at end of file +} diff --git a/upup/pkg/fi/cloudup/populate_cluster_spec.go b/upup/pkg/fi/cloudup/populate_cluster_spec.go index 8a9c07e35b..987c3a169b 100644 --- a/upup/pkg/fi/cloudup/populate_cluster_spec.go +++ b/upup/pkg/fi/cloudup/populate_cluster_spec.go @@ -24,6 +24,7 @@ import ( "text/template" "github.com/golang/glog" + api "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops/registry" "k8s.io/kops/pkg/apis/kops/util" diff --git a/upup/pkg/fi/cloudup/vspheretasks/attachiso.go b/upup/pkg/fi/cloudup/vspheretasks/attachiso.go index d2c83dcde7..6baf118412 100644 --- a/upup/pkg/fi/cloudup/vspheretasks/attachiso.go +++ b/upup/pkg/fi/cloudup/vspheretasks/attachiso.go @@ -21,13 +21,7 @@ package vspheretasks import ( "bytes" "fmt" - "github.com/golang/glog" - "github.com/pborman/uuid" "io/ioutil" - "k8s.io/kops/pkg/apis/kops" - "k8s.io/kops/pkg/model" - "k8s.io/kops/upup/pkg/fi" - "k8s.io/kops/upup/pkg/fi/cloudup/vsphere" "net" "net/url" "os" @@ -35,6 +29,14 @@ import ( "path/filepath" "runtime" "strings" + + "github.com/golang/glog" + "github.com/pborman/uuid" + + "k8s.io/kops/pkg/apis/kops" + "k8s.io/kops/pkg/model" + "k8s.io/kops/upup/pkg/fi" + "k8s.io/kops/upup/pkg/fi/cloudup/vsphere" ) // AttachISO represents the cloud-init ISO file attached to a VM on vSphere cloud. @@ -44,7 +46,7 @@ type AttachISO struct { VM *VirtualMachine IG *kops.InstanceGroup BootstrapScript *model.BootstrapScript - EtcdClusters []*kops.EtcdClusterSpec + Spec *kops.ClusterSpec } var _ fi.HasName = &AttachISO{} @@ -91,8 +93,7 @@ func (_ *AttachISO) CheckChanges(a, e, changes *AttachISO) error { // RenderVSphere executes the actual task logic, for vSphere cloud. func (_ *AttachISO) RenderVSphere(t *vsphere.VSphereAPITarget, a, e, changes *AttachISO) error { - // TODO #3071 .. need to replace the nil for http proxy support - startupScript, err := changes.BootstrapScript.ResourceNodeUp(changes.IG, nil) + startupScript, err := changes.BootstrapScript.ResourceNodeUp(changes.IG, changes.Spec) if err != nil { return fmt.Errorf("error on resource nodeup: %v", err) } @@ -196,7 +197,7 @@ func getVolMetadata(changes *AttachISO) (string, error) { var volsMetadata []vsphere.VolumeMetadata // Creating vsphere.VolumeMetadata using clusters EtcdClusterSpec - for i, etcd := range changes.EtcdClusters { + for i, etcd := range changes.Spec.EtcdClusters { volMetadata := vsphere.VolumeMetadata{} volMetadata.EtcdClusterName = etcd.Name volMetadata.VolumeId = vsphere.GetVolumeId(i + 1)