From c8e4a1caf8aae0b5b5ce49965c759c1341644d41 Mon Sep 17 00:00:00 2001 From: Rohith Date: Tue, 9 Jan 2018 17:34:39 +0000 Subject: [PATCH] Kubernetes Calico TLS The current implementation when Etcd TLS was added does not support using calico as the configuration and client certificates are not present. This PR updates the calico manifests and adds the distribution of the client certificate --- cmd/kops/integration_test.go | 6 +- cmd/kops/update_cluster.go | 13 ++-- nodeup/pkg/model/calico.go | 54 ++++++++++++++ nodeup/pkg/model/context.go | 53 ++++++++++++++ nodeup/pkg/model/protokube.go | 56 +-------------- pkg/assets/builder.go | 9 ++- pkg/model/iam.go | 1 - pkg/model/iam/iam_builder.go | 33 ++++++--- pkg/model/pki.go | 37 ++++++---- .../k8s-1.6.yaml.template | 70 +++++++++++++++++-- .../k8s-1.7.yaml.template | 68 +++++++++++++++++- .../pkg/fi/cloudup/bootstrapchannelbuilder.go | 22 ++---- upup/pkg/fi/cloudup/template_functions.go | 34 ++++++--- upup/pkg/fi/nodeup/command.go | 4 ++ 14 files changed, 335 insertions(+), 125 deletions(-) create mode 100644 nodeup/pkg/model/calico.go diff --git a/cmd/kops/integration_test.go b/cmd/kops/integration_test.go index 0ea4dbf1a7..1891521eb9 100644 --- a/cmd/kops/integration_test.go +++ b/cmd/kops/integration_test.go @@ -36,14 +36,14 @@ import ( "k8s.io/kops/cmd/kops/util" "k8s.io/kops/pkg/diff" + "k8s.io/kops/pkg/featureflag" "k8s.io/kops/pkg/jsonutils" "k8s.io/kops/pkg/testutils" + "k8s.io/kops/upup/pkg/fi/cloudup" + "k8s.io/kops/upup/pkg/fi/cloudup/gce" "github.com/ghodss/yaml" "golang.org/x/crypto/ssh" - "k8s.io/kops/pkg/featureflag" - "k8s.io/kops/upup/pkg/fi/cloudup" - "k8s.io/kops/upup/pkg/fi/cloudup/gce" ) // updateClusterTestBase is added automatically to the srcDir on all diff --git a/cmd/kops/update_cluster.go b/cmd/kops/update_cluster.go index b97560f189..7d3af48eeb 100644 --- a/cmd/kops/update_cluster.go +++ b/cmd/kops/update_cluster.go @@ -207,19 +207,18 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd } applyCmd := &cloudup.ApplyClusterCmd{ - Cluster: cluster, - Models: strings.Split(c.Models, ","), Clientset: clientset, - TargetName: targetName, - OutDir: c.OutDir, + Cluster: cluster, DryRun: isDryrun, - MaxTaskDuration: c.MaxTaskDuration, InstanceGroups: instanceGroups, + MaxTaskDuration: c.MaxTaskDuration, + Models: strings.Split(c.Models, ","), + OutDir: c.OutDir, Phase: phase, + TargetName: targetName, } - err = applyCmd.Run() - if err != nil { + if err := applyCmd.Run(); err != nil { return err } diff --git a/nodeup/pkg/model/calico.go b/nodeup/pkg/model/calico.go new file mode 100644 index 0000000000..192402b89a --- /dev/null +++ b/nodeup/pkg/model/calico.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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. +*/ + +package model + +import ( + "fmt" + + "k8s.io/kops/upup/pkg/fi" +) + +// CalicoBuilder configures the calico CNI provider +type CalicoBuilder struct { + *NodeupModelContext +} + +var _ fi.ModelBuilder = &CalicoBuilder{} + +// Build is responsible for performing any setup to the calico CNI provider +func (b *CalicoBuilder) Build(c *fi.ModelBuilderContext) error { + // @check if tls is enabled and if so, we need to download the client certificates + if b.UseEtcdTLS() { + name := "calico-client" + dirname := "calico" + ca := fmt.Sprintf("%s/ca.pem", dirname) + certificate := fmt.Sprintf("%s/%s.pem", dirname, name) + key := fmt.Sprintf("%s/%s-key.pem", dirname, name) + + if err := b.BuildCertificateTask(c, name, certificate); err != nil { + return err + } + if err := b.BuildPrivateTask(c, name, key); err != nil { + return err + } + if err := b.BuildCertificateTask(c, fi.CertificateId_CA, ca); err != nil { + return err + } + } + + return nil +} diff --git a/nodeup/pkg/model/context.go b/nodeup/pkg/model/context.go index b4f43b62d0..827d153763 100644 --- a/nodeup/pkg/model/context.go +++ b/nodeup/pkg/model/context.go @@ -28,6 +28,7 @@ import ( "k8s.io/kops/pkg/apis/nodeup" "k8s.io/kops/pkg/kubeconfig" "k8s.io/kops/upup/pkg/fi" + "k8s.io/kops/upup/pkg/fi/nodeup/nodetasks" ) // NodeupModelContext is the context supplied the nodeup tasks @@ -268,3 +269,55 @@ func (c *NodeupModelContext) KubectlPath() string { } return kubeletCommand } + +// BuildCertificateTask is responsible for build a certificate request task +func (c *NodeupModelContext) BuildCertificateTask(ctx *fi.ModelBuilderContext, name, filename string) error { + cert, err := c.KeyStore.FindCert(name) + if err != nil { + return err + } + + if cert == nil { + return fmt.Errorf("certificate %q not found", name) + } + + serialized, err := cert.AsString() + if err != nil { + return err + } + + ctx.AddTask(&nodetasks.File{ + Path: filepath.Join(c.PathSrvKubernetes(), filename), + Contents: fi.NewStringResource(serialized), + Type: nodetasks.FileType_File, + Mode: s("0400"), + }) + + return nil +} + +// BuildPrivateKeyTask is responsible for build a certificate request task +func (c *NodeupModelContext) BuildPrivateTask(ctx *fi.ModelBuilderContext, name, filename string) error { + cert, err := c.KeyStore.FindPrivateKey(name) + if err != nil { + return err + } + + if cert == nil { + return fmt.Errorf("private key %q not found", name) + } + + serialized, err := cert.AsString() + if err != nil { + return err + } + + ctx.AddTask(&nodetasks.File{ + Path: filepath.Join(c.PathSrvKubernetes(), filename), + Contents: fi.NewStringResource(serialized), + Type: nodetasks.FileType_File, + Mode: s("0400"), + }) + + return nil +} diff --git a/nodeup/pkg/model/protokube.go b/nodeup/pkg/model/protokube.go index bc50f666f9..687f210596 100644 --- a/nodeup/pkg/model/protokube.go +++ b/nodeup/pkg/model/protokube.go @@ -70,12 +70,12 @@ func (t *ProtokubeBuilder) Build(c *fi.ModelBuilderContext) error { // retrieve the etcd peer certificates and private keys from the keystore if t.UseEtcdTLS() { for _, x := range []string{"etcd", "etcd-client"} { - if err := t.buildCertificateTask(c, x, fmt.Sprintf("%s.pem", x)); err != nil { + if err := t.BuildCertificateTask(c, x, fmt.Sprintf("%s.pem", x)); err != nil { return err } } for _, x := range []string{"etcd", "etcd-client"} { - if err := t.buildPrivateTask(c, x, fmt.Sprintf("%s-key.pem", x)); err != nil { + if err := t.BuildPrivateTask(c, x, fmt.Sprintf("%s-key.pem", x)); err != nil { return err } } @@ -378,55 +378,3 @@ func (t *ProtokubeBuilder) writeProxyEnvVars(buffer *bytes.Buffer) { buffer.WriteString(" ") } } - -// buildCertificateTask is responsible for build a certificate request task -func (t *ProtokubeBuilder) buildCertificateTask(c *fi.ModelBuilderContext, name, filename string) error { - cert, err := t.KeyStore.FindCert(name) - if err != nil { - return err - } - - if cert == nil { - return fmt.Errorf("certificate %q not found", name) - } - - serialized, err := cert.AsString() - if err != nil { - return err - } - - c.AddTask(&nodetasks.File{ - Path: filepath.Join(t.PathSrvKubernetes(), filename), - Contents: fi.NewStringResource(serialized), - Type: nodetasks.FileType_File, - Mode: s("0400"), - }) - - return nil -} - -// buildPrivateKeyTask is responsible for build a certificate request task -func (t *ProtokubeBuilder) buildPrivateTask(c *fi.ModelBuilderContext, name, filename string) error { - cert, err := t.KeyStore.FindPrivateKey(name) - if err != nil { - return err - } - - if cert == nil { - return fmt.Errorf("private key %q not found", name) - } - - serialized, err := cert.AsString() - if err != nil { - return err - } - - c.AddTask(&nodetasks.File{ - Path: filepath.Join(t.PathSrvKubernetes(), filename), - Contents: fi.NewStringResource(serialized), - Type: nodetasks.FileType_File, - Mode: s("0400"), - }) - - return nil -} diff --git a/pkg/assets/builder.go b/pkg/assets/builder.go index 01c3b999c4..7b6cc673d5 100644 --- a/pkg/assets/builder.go +++ b/pkg/assets/builder.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/golang/glog" + "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/featureflag" "k8s.io/kops/pkg/kubemanifest" @@ -51,7 +52,6 @@ type ContainerAsset struct { // DockerImage will be the name of the container we should run. // This is used to copy a container to a ContainerRegistry. DockerImage string - // CanonicalLocation will be the source location of the container. CanonicalLocation string } @@ -60,10 +60,8 @@ type ContainerAsset struct { type FileAsset struct { // FileURL is the URL of a file that is accessed by a Kubernetes cluster. FileURL *url.URL - // CanonicalFileURL is the source URL of a file. This is used to copy a file to a FileRepository. CanonicalFileURL *url.URL - // SHAValue is the SHA hash of the FileAsset. SHAValue string } @@ -84,6 +82,7 @@ func (a *AssetBuilder) RemapManifest(data []byte) ([]byte, error) { if !RewriteManifests.Enabled() { return data, nil } + manifests, err := kubemanifest.LoadManifestsFrom(data) if err != nil { return nil, err @@ -92,10 +91,10 @@ func (a *AssetBuilder) RemapManifest(data []byte) ([]byte, error) { var yamlSeparator = []byte("\n---\n\n") var remappedManifests [][]byte for _, manifest := range manifests { - err := manifest.RemapImages(a.RemapImage) - if err != nil { + if err := manifest.RemapImages(a.RemapImage); err != nil { return nil, fmt.Errorf("error remapping images: %v", err) } + y, err := manifest.ToYAML() if err != nil { return nil, fmt.Errorf("error re-marshalling manifest: %v", err) diff --git a/pkg/model/iam.go b/pkg/model/iam.go index 87d2fe5b5b..4f7fd39de9 100644 --- a/pkg/model/iam.go +++ b/pkg/model/iam.go @@ -143,7 +143,6 @@ func (b *IAMModelBuilder) Build(c *fi.ModelBuilderContext) error { if b.Cluster.Spec.AdditionalPolicies != nil { roleAsString := reflect.ValueOf(role).String() additionalPolicies := *(b.Cluster.Spec.AdditionalPolicies) - additionalPolicy = additionalPolicies[strings.ToLower(roleAsString)] } diff --git a/pkg/model/iam/iam_builder.go b/pkg/model/iam/iam_builder.go index d0aebe4f2c..64d8be8422 100644 --- a/pkg/model/iam/iam_builder.go +++ b/pkg/model/iam/iam_builder.go @@ -359,15 +359,30 @@ func (b *PolicyBuilder) AddS3Permissions(p *Policy) (*Policy, error) { ), }) - if b.Cluster.Spec.Networking != nil && b.Cluster.Spec.Networking.Kuberouter != nil { - p.Statement = append(p.Statement, &Statement{ - Sid: "kopsK8sS3NodeBucketGetKuberouter", - Effect: StatementEffectAllow, - Action: stringorslice.Slice([]string{"s3:Get*"}), - Resource: stringorslice.Of( - strings.Join([]string{b.IAMPrefix(), ":s3:::", iamS3Path, "/pki/private/kube-router/*"}, ""), - ), - }) + if b.Cluster.Spec.Networking != nil { + // @check if kuberoute is enabled and permit access to the private key + if b.Cluster.Spec.Networking.Kuberouter != nil { + p.Statement = append(p.Statement, &Statement{ + Sid: "kopsK8sS3NodeBucketGetKuberouter", + Effect: StatementEffectAllow, + Action: stringorslice.Slice([]string{"s3:Get*"}), + Resource: stringorslice.Of( + strings.Join([]string{b.IAMPrefix(), ":s3:::", iamS3Path, "/pki/private/kube-router/*"}, ""), + ), + }) + } + + // @check if calico is enabled as the CNI provider and permit access to the client TLS certificate by default + if b.Cluster.Spec.Networking.Calico != nil { + p.Statement = append(p.Statement, &Statement{ + Sid: "kopsK8sS3NodeBucketGetCalicoClient", + Effect: StatementEffectAllow, + Action: stringorslice.Slice([]string{"s3:Get*"}), + Resource: stringorslice.Of( + strings.Join([]string{b.IAMPrefix(), ":s3:::", iamS3Path, "/pki/private/calico-client/*"}, ""), + ), + }) + } } } } diff --git a/pkg/model/pki.go b/pkg/model/pki.go index fd14216706..139f66675b 100644 --- a/pkg/model/pki.go +++ b/pkg/model/pki.go @@ -109,23 +109,30 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error { // For clients assuming we are using etcdv3 is can switch on user authentication and map the common names for auth. if b.UseEtcdTLS() { alternativeNames := []string{fmt.Sprintf("*.internal.%s", b.ClusterName()), "localhost", "127.0.0.1"} - { - // @question should wildcard's be here instead of generating per node. If we ever provide the - // ability to resize the master, this will become a blocker + // @question should wildcard's be here instead of generating per node. If we ever provide the + // ability to resize the master, this will become a blocker + c.AddTask(&fitasks.Keypair{ + AlternateNames: alternativeNames, + Lifecycle: b.Lifecycle, + Name: fi.String("etcd"), + Subject: "cn=etcd", + Type: "server", + Signer: defaultCA, + }) + c.AddTask(&fitasks.Keypair{ + Name: fi.String("etcd-client"), + Lifecycle: b.Lifecycle, + Subject: "cn=etcd-client", + Type: "client", + Signer: defaultCA, + }) + + // @check if calico is enabled as the CNI provider + if b.KopsModelContext.Cluster.Spec.Networking.Calico != nil { c.AddTask(&fitasks.Keypair{ - AlternateNames: alternativeNames, - Lifecycle: b.Lifecycle, - Name: fi.String("etcd"), - Subject: "cn=etcd", - Type: "server", - Signer: defaultCA, - }) - } - { - c.AddTask(&fitasks.Keypair{ - Name: fi.String("etcd-client"), + Name: fi.String("calico-client"), Lifecycle: b.Lifecycle, - Subject: "cn=etcd-client", + Subject: "cn=calico-client", Type: "client", Signer: defaultCA, }) diff --git a/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.6.yaml.template b/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.6.yaml.template index a200143327..f1c9b30f79 100644 --- a/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.6.yaml.template +++ b/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.6.yaml.template @@ -1,3 +1,4 @@ +{{- $etcd_scheme := EtcdScheme }} # This ConfigMap is used to configure a self-hosted Calico installation. kind: ConfigMap apiVersion: v1 @@ -9,7 +10,7 @@ data: etcd_endpoints: "{{ $cluster := index .EtcdClusters 0 -}} {{- range $j, $member := $cluster.Members -}} {{- if $j }},{{ end -}} - http://etcd-{{ $member.Name }}.internal.{{ ClusterName }}:4001 + {{ $etcd_scheme }}://etcd-{{ $member.Name }}.internal.{{ ClusterName }}:4001 {{- end }}" # Configure the Calico backend to use. @@ -21,6 +22,12 @@ data: "name": "k8s-pod-network", "type": "calico", "etcd_endpoints": "__ETCD_ENDPOINTS__", + {{- if eq $etcd_scheme "https" }} + "etcd_ca_cert_file": "/srv/kubernetes/calico/ca.pem", + "etcd_cert_file": "/srv/kubernetes/calico/calico-client.pem", + "etcd_key_file": "/srv/kubernetes/calico/calico-client-key.pem", + "etcd_scheme": "https", + {{- end }} "log_level": "info", "ipam": { "type": "calico-ipam" @@ -141,6 +148,14 @@ spec: configMapKeyRef: name: calico-config key: etcd_endpoints + {{- if eq $etcd_scheme "https" }} + - name: ETCD_CERT_FILE + value: /certs/calico-client.pem + - name: ETCD_KEY_FILE + value: /certs/calico-client-key.pem + - name: ETCD_CA_CERT_FILE + value: /certs/ca.pem + {{- end }} # Enable BGP. Disable to enforce policy only. - name: CALICO_NETWORKING_BACKEND valueFrom: @@ -182,6 +197,11 @@ spec: - mountPath: /etc/hosts name: etc-hosts readOnly: true + {{- if eq $etcd_scheme "https" }} + - mountPath: /certs + name: calico + readOnly: true + {{- end }} # This container installs the Calico CNI binaries # and CNI network config file on each node. - name: install-cni @@ -234,6 +254,11 @@ spec: - name: etc-hosts hostPath: path: /etc/hosts + {{- if eq $etcd_scheme "https" }} + - name: calico + hostPath: + path: /srv/kubernetes/calico + {{- end }} --- @@ -271,16 +296,32 @@ spec: configMapKeyRef: name: calico-config key: etcd_endpoints - + {{- if eq $etcd_scheme "https" }} + - name: ETCD_CERT_FILE + value: /certs/calico-client.pem + - name: ETCD_KEY_FILE + value: /certs/calico-client-key.pem + - name: ETCD_CA_CERT_FILE + value: /certs/ca.pem + {{- end }} volumeMounts: - # Necessary for gossip based DNS - mountPath: /etc/hosts name: etc-hosts readOnly: true + {{- if eq $etcd_scheme "https" }} + - mountPath: /certs + name: calico + readOnly: true + {{- end }} volumes: - name: etc-hosts hostPath: path: /etc/hosts + {{- if eq $etcd_scheme "https" }} + - name: calico + hostPath: + path: /srv/kubernetes/calico + {{- end }} --- # This manifest deploys the Calico Kubernetes controllers. @@ -328,8 +369,27 @@ spec: configMapKeyRef: name: calico-config key: etcd_endpoints - - + {{- if eq $etcd_scheme "https" }} + - name: ETCD_CERT_FILE + value: /certs/calico-client.pem + - name: ETCD_KEY_FILE + value: /certs/calico-client-key.pem + - name: ETCD_CA_CERT_FILE + value: /certs/ca.pem + volumeMounts: + - mountPath: /certs + name: calico + readOnly: true + {{- end }} + volumes: + - name: etc-hosts + hostPath: + path: /etc/hosts + {{- if eq $etcd_scheme "https" }} + - name: calico + hostPath: + path: /srv/kubernetes/calico + {{- end }} {{ if and (eq .CloudProvider "aws") (.Networking.Calico.CrossSubnet) -}} # This manifest installs the k8s-ec2-srcdst container, which disables diff --git a/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.7.yaml.template b/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.7.yaml.template index b36e517b70..9bccd75d72 100644 --- a/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.7.yaml.template +++ b/upup/models/cloudup/resources/addons/networking.projectcalico.org/k8s-1.7.yaml.template @@ -1,3 +1,4 @@ +{{- $etcd_scheme := EtcdScheme }} # This ConfigMap is used to configure a self-hosted Calico installation. kind: ConfigMap apiVersion: v1 @@ -9,7 +10,7 @@ data: etcd_endpoints: "{{ $cluster := index .EtcdClusters 0 -}} {{- range $j, $member := $cluster.Members -}} {{- if $j }},{{ end -}} - http://etcd-{{ $member.Name }}.internal.{{ ClusterName }}:4001 + {{ $etcd_scheme }}://etcd-{{ $member.Name }}.internal.{{ ClusterName }}:4001 {{- end }}" # Configure the Calico backend to use. @@ -24,6 +25,12 @@ data: { "type": "calico", "etcd_endpoints": "__ETCD_ENDPOINTS__", + {{- if eq $etcd_scheme "https" }} + "etcd_ca_cert_file": "/srv/kubernetes/calico/ca.pem", + "etcd_cert_file": "/srv/kubernetes/calico/calico-client.pem", + "etcd_key_file": "/srv/kubernetes/calico/calico-client-key.pem", + "etcd_scheme": "https", + {{- end }} "log_level": "info", "ipam": { "type": "calico-ipam" @@ -152,6 +159,14 @@ spec: configMapKeyRef: name: calico-config key: etcd_endpoints + {{- if eq $etcd_scheme "https" }} + - name: ETCD_CERT_FILE + value: /certs/calico-client.pem + - name: ETCD_KEY_FILE + value: /certs/calico-client-key.pem + - name: ETCD_CA_CERT_FILE + value: /certs/ca.pem + {{- end }} # Enable BGP. Disable to enforce policy only. - name: CALICO_NETWORKING_BACKEND valueFrom: @@ -193,6 +208,11 @@ spec: - mountPath: /etc/hosts name: etc-hosts readOnly: true + {{- if eq $etcd_scheme "https" }} + - mountPath: /certs + name: calico + readOnly: true + {{- end }} # This container installs the Calico CNI binaries # and CNI network config file on each node. - name: install-cni @@ -245,6 +265,11 @@ spec: - name: etc-hosts hostPath: path: /etc/hosts + {{- if eq $etcd_scheme "https" }} + - name: calico + hostPath: + path: /srv/kubernetes/calico + {{- end }} --- @@ -293,7 +318,27 @@ spec: configMapKeyRef: name: calico-config key: etcd_endpoints - + {{- if eq $etcd_scheme "https" }} + - name: ETCD_CERT_FILE + value: /certs/calico-client.pem + - name: ETCD_KEY_FILE + value: /certs/calico-client-key.pem + - name: ETCD_CA_CERT_FILE + value: /certs/ca.pem + volumeMounts: + - mountPath: /certs + name: calico + readOnly: true + {{- end }} + volumes: + - name: etc-hosts + hostPath: + path: /etc/hosts + {{- if eq $etcd_scheme "https" }} + - name: calico + hostPath: + path: /srv/kubernetes/calico + {{- end }} --- # This deployment turns off the old "policy-controller". It should remain at 0 replicas, and then @@ -330,16 +375,33 @@ spec: configMapKeyRef: name: calico-config key: etcd_endpoints - + {{- if eq $etcd_scheme "https" }} + - name: ETCD_CERT_FILE + value: /certs/calico-client.pem + - name: ETCD_KEY_FILE + value: /certs/calico-client-key.pem + - name: ETCD_CA_CERT_FILE + value: /certs/ca.pem + {{- end }} volumeMounts: # Necessary for gossip based DNS - mountPath: /etc/hosts name: etc-hosts readOnly: true + {{- if eq $etcd_scheme "https" }} + - mountPath: /certs + name: calico + readOnly: true + {{ end }} volumes: - name: etc-hosts hostPath: path: /etc/hosts + {{- if eq $etcd_scheme "https" }} + - name: calico + hostPath: + path: /srv/kubernetes/calico + {{- end }} {{ if and (eq .CloudProvider "aws") (.Networking.Calico.CrossSubnet) -}} # This manifest installs the k8s-ec2-srcdst container, which disables diff --git a/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go b/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go index 9671030a2b..238a62d6fd 100644 --- a/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go +++ b/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go @@ -41,7 +41,6 @@ var _ fi.ModelBuilder = &BootstrapChannelBuilder{} // Build is responsible for adding the addons to the channel func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error { - addons, manifests, err := b.buildManifest() if err != nil { return err @@ -53,15 +52,13 @@ func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error { } name := b.cluster.ObjectMeta.Name + "-addons-bootstrap" - tasks := c.Tasks tasks[name] = &fitasks.ManagedFile{ - Name: fi.String(name), + Contents: fi.WrapResource(fi.NewBytesResource(addonsYAML)), Lifecycle: b.Lifecycle, - - Location: fi.String("addons/bootstrap-channel.yaml"), - Contents: fi.WrapResource(fi.NewBytesResource(addonsYAML)), + Location: fi.String("addons/bootstrap-channel.yaml"), + Name: fi.String(name), } for key, manifest := range manifests { @@ -83,11 +80,10 @@ func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error { } tasks[name] = &fitasks.ManagedFile{ - Name: fi.String(name), + Contents: fi.WrapResource(fi.NewBytesResource(manifestBytes)), Lifecycle: b.Lifecycle, - - Location: fi.String(manifest), - Contents: fi.WrapResource(fi.NewBytesResource(manifestBytes)), + Location: fi.String(manifest), + Name: fi.String(name), } } @@ -95,16 +91,14 @@ func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error { } func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[string]string, error) { - manifests := make(map[string]string) - addons := &channelsapi.Addons{} addons.Kind = "Addons" addons.ObjectMeta.Name = "bootstrap" + manifests := make(map[string]string) { key := "core.addons.k8s.io" version := "1.4.0" - location := key + "/v" + version + ".yaml" addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{ @@ -174,7 +168,6 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri { key := "limit-range.addons.k8s.io" version := "1.5.0" - location := key + "/v" + version + ".yaml" addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{ @@ -686,7 +679,6 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri if b.cluster.Spec.KubeScheduler.UsePolicyConfigMap != nil { key := "scheduler.addons.k8s.io" version := "1.7.0" - location := key + "/v" + version + ".yaml" addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{ diff --git a/upup/pkg/fi/cloudup/template_functions.go b/upup/pkg/fi/cloudup/template_functions.go index b498314304..1ed1083dc9 100644 --- a/upup/pkg/fi/cloudup/template_functions.go +++ b/upup/pkg/fi/cloudup/template_functions.go @@ -43,25 +43,24 @@ import ( "k8s.io/kops/upup/pkg/fi/cloudup/gce" ) +// TemplateFunctions provides a collection of methods used throughout the templates type TemplateFunctions struct { cluster *kops.Cluster instanceGroups []*kops.InstanceGroup - - tags sets.String - region string - - modelContext *model.KopsModelContext + modelContext *model.KopsModelContext + region string + tags sets.String } // This will define the available functions we can use in our YAML models // If we are trying to get a new function implemented it MUST // be defined here. func (tf *TemplateFunctions) AddTo(dest template.FuncMap) { + dest["EtcdScheme"] = tf.EtcdScheme dest["SharedVPC"] = tf.SharedVPC - + dest["UseEtcdTLS"] = tf.UseEtcdTLS // Remember that we may be on a different arch from the target. Hard-code for now. dest["Arch"] = func() string { return "amd64" } - dest["replace"] = func(s, find, replace string) string { return strings.Replace(s, find, replace, -1) } @@ -71,7 +70,6 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) { dest["ClusterName"] = tf.modelContext.ClusterName dest["HasTag"] = tf.HasTag - dest["WithDefaultBool"] = func(v *bool, defaultValue bool) bool { if v != nil { return *v @@ -106,6 +104,26 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) { } } +// UseEtcdTLS checks if cluster is using etcd tls +func (tf *TemplateFunctions) UseEtcdTLS() bool { + for _, x := range tf.cluster.Spec.EtcdClusters { + if x.EnableEtcdTLS { + return true + } + } + + return false +} + +// EtcdScheme parses and grabs the protocol to the etcd cluster +func (tf *TemplateFunctions) EtcdScheme() string { + if tf.UseEtcdTLS() { + return "https" + } + + return "http" +} + // SharedVPC is a simple helper function which makes the templates for a shared VPC clearer func (tf *TemplateFunctions) SharedVPC() bool { return tf.cluster.SharedVPC() diff --git a/upup/pkg/fi/nodeup/command.go b/upup/pkg/fi/nodeup/command.go index 0d5311a674..476a206425 100644 --- a/upup/pkg/fi/nodeup/command.go +++ b/upup/pkg/fi/nodeup/command.go @@ -26,6 +26,7 @@ import ( "time" "github.com/golang/glog" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kops/nodeup/pkg/distros" "k8s.io/kops/nodeup/pkg/model" @@ -236,6 +237,9 @@ func (c *NodeUpCommand) Run(out io.Writer) error { } else { loader.Builders = append(loader.Builders, &model.KubeRouterBuilder{NodeupModelContext: modelContext}) } + if c.cluster.Spec.Networking.Calico != nil { + loader.Builders = append(loader.Builders, &model.CalicoBuilder{NodeupModelContext: modelContext}) + } taskMap, err := loader.Build(c.ModelDir) if err != nil {