mirror of https://github.com/kubernetes/kops.git
140 lines
3.7 KiB
Go
140 lines
3.7 KiB
Go
package cloudup
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"k8s.io/kops/upup/pkg/api"
|
|
"math/big"
|
|
"net"
|
|
"sort"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
type TemplateFunctions struct {
|
|
cluster *api.Cluster
|
|
tags map[string]struct{}
|
|
region string
|
|
}
|
|
|
|
func (tf *TemplateFunctions) WellKnownServiceIP(id int) (net.IP, error) {
|
|
_, cidr, err := net.ParseCIDR(tf.cluster.Spec.ServiceClusterIPRange)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing ServiceClusterIPRange %q: %v", tf.cluster.Spec.ServiceClusterIPRange, err)
|
|
}
|
|
|
|
ip4 := cidr.IP.To4()
|
|
if ip4 != nil {
|
|
n := binary.BigEndian.Uint32(ip4)
|
|
n += uint32(id)
|
|
serviceIP := make(net.IP, len(ip4))
|
|
binary.BigEndian.PutUint32(serviceIP, n)
|
|
return serviceIP, nil
|
|
}
|
|
|
|
ip6 := cidr.IP.To16()
|
|
if ip6 != nil {
|
|
baseIPInt := big.NewInt(0)
|
|
baseIPInt.SetBytes(ip6)
|
|
serviceIPInt := big.NewInt(0)
|
|
serviceIPInt.Add(big.NewInt(int64(id)), baseIPInt)
|
|
serviceIP := make(net.IP, len(ip6))
|
|
serviceIPBytes := serviceIPInt.Bytes()
|
|
for i := range serviceIPBytes {
|
|
serviceIP[len(serviceIP)-len(serviceIPBytes)+i] = serviceIPBytes[i]
|
|
}
|
|
return serviceIP, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("Unexpected IP address type for ServiceClusterIPRange: %s", tf.cluster.Spec.ServiceClusterIPRange)
|
|
}
|
|
|
|
func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
|
|
dest["EtcdClusterMemberTags"] = tf.EtcdClusterMemberTags
|
|
dest["SharedVPC"] = tf.SharedVPC
|
|
dest["WellKnownServiceIP"] = tf.WellKnownServiceIP
|
|
dest["AdminCIDR"] = tf.AdminCIDR
|
|
|
|
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"] = func() string {
|
|
return tf.cluster.Name
|
|
}
|
|
|
|
dest["HasTag"] = func(tag string) bool {
|
|
_, found := tf.tags[tag]
|
|
return found
|
|
}
|
|
|
|
dest["IAMPrefix"] = tf.IAMPrefix
|
|
dest["IAMServiceEC2"] = tf.IAMServiceEC2
|
|
|
|
}
|
|
|
|
func (tf *TemplateFunctions) EtcdClusterMemberTags(etcd *api.EtcdClusterSpec, m *api.EtcdMemberSpec) map[string]string {
|
|
tags := make(map[string]string)
|
|
|
|
var allMembers []string
|
|
|
|
for _, m := range etcd.Members {
|
|
allMembers = append(allMembers, m.Name)
|
|
}
|
|
|
|
sort.Strings(allMembers)
|
|
|
|
// This is the configuration of the etcd cluster
|
|
tags["k8s.io/etcd/"+etcd.Name] = m.Name + "/" + strings.Join(allMembers, ",")
|
|
|
|
// This says "only mount on a master"
|
|
tags["k8s.io/role/master"] = "1"
|
|
|
|
return tags
|
|
}
|
|
|
|
// SharedVPC is a simple helper function which makes the templates for a shared VPC clearer
|
|
func (tf *TemplateFunctions) SharedVPC() bool {
|
|
return tf.cluster.Spec.NetworkID != ""
|
|
}
|
|
|
|
// AdminCIDR returns the single CIDR that is allowed access to the admin ports of the cluster (22, 443 on master)
|
|
func (tf *TemplateFunctions) AdminCIDR() (string, error) {
|
|
if len(tf.cluster.Spec.AdminAccess) == 0 {
|
|
return "0.0.0.0/0", nil
|
|
}
|
|
if len(tf.cluster.Spec.AdminAccess) == 1 {
|
|
return tf.cluster.Spec.AdminAccess[0], nil
|
|
}
|
|
return "", fmt.Errorf("Multiple AdminAccess rules are not (currently) supported")
|
|
}
|
|
|
|
// IAMServiceEC2 returns the name of the IAM service for EC2 in the current region
|
|
// it is ec2.amazonaws.com everywhere but in cn-north, where it is ec2.amazonaws.com.cn
|
|
func (tf *TemplateFunctions) IAMServiceEC2() string {
|
|
switch tf.region {
|
|
case "cn-north-1":
|
|
return "ec2.amazonaws.com.cn"
|
|
default:
|
|
return "ec2.amazonaws.com"
|
|
}
|
|
}
|
|
|
|
// IAMPrefix returns the prefix for AWS ARNs in the current region, for use with IAM
|
|
// it is arn:aws everywhere but in cn-north, where it is arn:aws-cn
|
|
func (tf *TemplateFunctions) IAMPrefix() string {
|
|
switch tf.region {
|
|
case "cn-north-1":
|
|
return "arn:aws-cn"
|
|
default:
|
|
return "arn:aws"
|
|
}
|
|
}
|