kops/upup/pkg/fi/cloudup/template_functions.go

180 lines
5.2 KiB
Go

/*
Copyright 2016 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.
*/
/******************************************************************************
Template Functions are what map functions in the models, to internal logic in
kops. This is the point where we connect static YAML configuration to dynamic
runtime values in memory.
When defining a new function:
- Build the new function here
- Define the new function in AddTo()
dest["MyNewFunction"] = MyNewFunction // <-- Function Pointer
******************************************************************************/
package cloudup
import (
"encoding/base64"
"fmt"
"k8s.io/apimachinery/pkg/util/sets"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/model"
"k8s.io/kops/pkg/model/components"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"os"
"strings"
"text/template"
)
type TemplateFunctions struct {
cluster *api.Cluster
instanceGroups []*api.InstanceGroup
tags sets.String
region string
modelContext *model.KopsModelContext
}
// 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["SharedVPC"] = tf.SharedVPC
// Remember that we may be on a different arch from the target. Hard-code for now.
dest["Arch"] = func() string { return "amd64" }
dest["Base64Encode"] = func(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
}
dest["replace"] = func(s, find, replace string) string {
return strings.Replace(s, find, replace, -1)
}
dest["join"] = func(a []string, sep string) string {
return strings.Join(a, sep)
}
dest["ClusterName"] = tf.modelContext.ClusterName
dest["HasTag"] = tf.HasTag
dest["Image"] = tf.Image
dest["WithDefaultBool"] = func(v *bool, defaultValue bool) bool {
if v != nil {
return *v
}
return defaultValue
}
dest["GetInstanceGroup"] = tf.GetInstanceGroup
dest["CloudTags"] = tf.modelContext.CloudTagsForInstanceGroup
dest["KubeDNS"] = func() *api.KubeDNSConfig {
return tf.cluster.Spec.KubeDNS
}
dest["DnsControllerArgv"] = tf.DnsControllerArgv
// TODO: Only for GCE?
dest["EncodeGCELabel"] = gce.EncodeGCELabel
dest["DnsControllerImage"] = tf.DnsControllerImage
}
// SharedVPC is a simple helper function which makes the templates for a shared VPC clearer
func (tf *TemplateFunctions) SharedVPC() bool {
return tf.cluster.SharedVPC()
}
// Image returns the docker image name for the specified component
func (tf *TemplateFunctions) Image(component string) (string, error) {
return components.Image(component, &tf.cluster.Spec)
}
// HasTag returns true if the specified tag is set
func (tf *TemplateFunctions) HasTag(tag string) bool {
_, found := tf.tags[tag]
return found
}
// GetInstanceGroup returns the instance group with the specified name
func (tf *TemplateFunctions) GetInstanceGroup(name string) (*api.InstanceGroup, error) {
for _, ig := range tf.instanceGroups {
if ig.ObjectMeta.Name == name {
return ig, nil
}
}
return nil, fmt.Errorf("InstanceGroup %q not found", name)
}
func (tf *TemplateFunctions) DnsControllerArgv() ([]string, error) {
var argv []string
argv = append(argv, "/usr/bin/dns-controller")
argv = append(argv, "--watch-ingress=false")
switch fi.CloudProviderID(tf.cluster.Spec.CloudProvider) {
case fi.CloudProviderAWS:
argv = append(argv, "--dns=aws-route53")
case fi.CloudProviderGCE:
argv = append(argv, "--dns=google-clouddns")
case fi.CloudProviderVSphere:
argv = append(argv, "--dns=coredns")
argv = append(argv, "--dns-server="+*tf.cluster.Spec.CloudConfig.VSphereCoreDNSServer)
default:
return nil, fmt.Errorf("unhandled cloudprovider %q", tf.cluster.Spec.CloudProvider)
}
zone := tf.cluster.Spec.DNSZone
if zone != "" {
if strings.Contains(zone, ".") {
// match by name
argv = append(argv, "--zone="+zone)
} else {
// match by id
argv = append(argv, "--zone=*/"+zone)
}
}
// permit wildcard updates
argv = append(argv, "--zone=*/*")
// Verbose, but not crazy logging
argv = append(argv, "-v=2")
return argv, nil
}
// TODO: this is a work-around before vSphere support is getting merged into upstream kops.
// To use CoreDNS supported DNS Controller:
// 1. DOCKER_REGISTRY=[your docker hub repo] make dns-controller-push
// 2. export VSPHERE_DNSCONTROLLER_IMAGE=[your docker hub repo]
// 3. make kops and create/apply cluster
func (tf *TemplateFunctions) DnsControllerImage() (string, error) {
image := os.Getenv("VSPHERE_DNSCONTROLLER_IMAGE")
if fi.CloudProviderID(tf.cluster.Spec.CloudProvider) != fi.CloudProviderVSphere || image == "" {
return "kope/dns-controller", nil
} else {
return image, nil
}
}