Merge pull request #4240 from gambol99/calico_tls

Kubernetes Calico TLS
This commit is contained in:
k8s-ci-robot 2018-02-15 09:25:38 -08:00 committed by GitHub
commit 2bf86134a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 335 additions and 125 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)]
}

View File

@ -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/*"}, ""),
),
})
}
}
}
}

View File

@ -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,
})

View File

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

View File

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

View File

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

View File

@ -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()

View File

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