mirror of https://github.com/kubernetes/kops.git
Customize KubeDNS
This PR adds the ability for users to customize the kubedns upstream nameservers and provider stubdomains, as per [here](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/)
This commit is contained in:
parent
a717a035d5
commit
de977e627e
|
@ -286,22 +286,24 @@ type LoadBalancerAccessSpec struct {
|
|||
|
||||
// KubeDNSConfig defines the kube dns configuration
|
||||
type KubeDNSConfig struct {
|
||||
// Image is the name of the docker image to run
|
||||
// Deprecated as this is now in the addon
|
||||
Image string `json:"image,omitempty"`
|
||||
// Replicas is the number of pod replicas
|
||||
// Deprecated as this is now in the addon, and controlled by autoscaler
|
||||
Replicas int `json:"replicas,omitempty"`
|
||||
// Domain is the dns domain
|
||||
Domain string `json:"domain,omitempty"`
|
||||
// ServerIP is the server ip
|
||||
ServerIP string `json:"serverIP,omitempty"`
|
||||
// CacheMaxSize is the maximum entries to keep in dnsmaq
|
||||
CacheMaxSize int `json:"cacheMaxSize,omitempty"`
|
||||
// CacheMaxConcurrent is the maximum number of concurrent queries for dnsmasq
|
||||
CacheMaxConcurrent int `json:"cacheMaxConcurrent,omitempty"`
|
||||
// Domain is the dns domain
|
||||
Domain string `json:"domain,omitempty"`
|
||||
// Image is the name of the docker image to run - @deprecated as this is now in the addon
|
||||
Image string `json:"image,omitempty"`
|
||||
// Replicas is the number of pod replicas - @deprecated as this is now in the addon and controlled by autoscaler
|
||||
Replicas int `json:"replicas,omitempty"`
|
||||
// Provider indicates whether CoreDNS or kube-dns will be the default service discovery.
|
||||
Provider string `json:"provider,omitempty"`
|
||||
// ServerIP is the server ip
|
||||
ServerIP string `json:"serverIP,omitempty"`
|
||||
// StubDomains redirects a domains to another DNS service
|
||||
StubDomains map[string][]string `json:"stubDomains,omitempty"`
|
||||
// UpstreamNameservers sets the upstream nameservers for queries not on the cluster domain
|
||||
UpstreamNameservers []string `json:"upstreamNameservers,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalDNSConfig are options of the dns-controller
|
||||
|
|
|
@ -285,22 +285,24 @@ type LoadBalancerAccessSpec struct {
|
|||
|
||||
// KubeDNSConfig defines the kube dns configuration
|
||||
type KubeDNSConfig struct {
|
||||
// Image is the name of the docker image to run
|
||||
// Deprecated as this is now in the addon
|
||||
Image string `json:"image,omitempty"`
|
||||
// Replicas is the number of pod replicas
|
||||
// Deprecated as this is now in the addon, and controlled by autoscaler
|
||||
Replicas int `json:"replicas,omitempty"`
|
||||
// Domain is the dns domain
|
||||
Domain string `json:"domain,omitempty"`
|
||||
// ServerIP is the server ip
|
||||
ServerIP string `json:"serverIP,omitempty"`
|
||||
// CacheMaxSize is the maximum entries to keep in dnsmaq
|
||||
CacheMaxSize int `json:"cacheMaxSize,omitempty"`
|
||||
// CacheMaxConcurrent is the maximum number of concurrent queries for dnsmasq
|
||||
CacheMaxConcurrent int `json:"cacheMaxConcurrent,omitempty"`
|
||||
// Domain is the dns domain
|
||||
Domain string `json:"domain,omitempty"`
|
||||
// Image is the name of the docker image to run - @deprecated as this is now in the addon
|
||||
Image string `json:"image,omitempty"`
|
||||
// Replicas is the number of pod replicas - @deprecated as this is now in the addon, and controlled by autoscaler
|
||||
Replicas int `json:"replicas,omitempty"`
|
||||
// Provider indicates whether CoreDNS or kube-dns will be the default service discovery.
|
||||
Provider string `json:"provider,omitempty"`
|
||||
// ServerIP is the server ip
|
||||
ServerIP string `json:"serverIP,omitempty"`
|
||||
// StubDomains redirects a domains to another DNS service
|
||||
StubDomains map[string][]string `json:"stubDomains,omitempty"`
|
||||
// UpstreamNameservers sets the upstream nameservers for queries not on the cluster domain
|
||||
UpstreamNameservers []string `json:"upstreamNameservers,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalDNSConfig are options of the dns-controller
|
||||
|
|
|
@ -2093,13 +2093,15 @@ func Convert_kops_KubeControllerManagerConfig_To_v1alpha1_KubeControllerManagerC
|
|||
}
|
||||
|
||||
func autoConvert_v1alpha1_KubeDNSConfig_To_kops_KubeDNSConfig(in *KubeDNSConfig, out *kops.KubeDNSConfig, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Domain = in.Domain
|
||||
out.ServerIP = in.ServerIP
|
||||
out.CacheMaxSize = in.CacheMaxSize
|
||||
out.CacheMaxConcurrent = in.CacheMaxConcurrent
|
||||
out.Domain = in.Domain
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Provider = in.Provider
|
||||
out.ServerIP = in.ServerIP
|
||||
out.StubDomains = in.StubDomains
|
||||
out.UpstreamNameservers = in.UpstreamNameservers
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2109,13 +2111,15 @@ func Convert_v1alpha1_KubeDNSConfig_To_kops_KubeDNSConfig(in *KubeDNSConfig, out
|
|||
}
|
||||
|
||||
func autoConvert_kops_KubeDNSConfig_To_v1alpha1_KubeDNSConfig(in *kops.KubeDNSConfig, out *KubeDNSConfig, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Domain = in.Domain
|
||||
out.ServerIP = in.ServerIP
|
||||
out.CacheMaxSize = in.CacheMaxSize
|
||||
out.CacheMaxConcurrent = in.CacheMaxConcurrent
|
||||
out.Domain = in.Domain
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Provider = in.Provider
|
||||
out.ServerIP = in.ServerIP
|
||||
out.StubDomains = in.StubDomains
|
||||
out.UpstreamNameservers = in.UpstreamNameservers
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -706,7 +706,7 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
|
|||
*out = nil
|
||||
} else {
|
||||
*out = new(KubeDNSConfig)
|
||||
**out = **in
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.KubeAPIServer != nil {
|
||||
|
@ -2107,6 +2107,23 @@ func (in *KubeControllerManagerConfig) DeepCopy() *KubeControllerManagerConfig {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeDNSConfig) DeepCopyInto(out *KubeDNSConfig) {
|
||||
*out = *in
|
||||
if in.StubDomains != nil {
|
||||
in, out := &in.StubDomains, &out.StubDomains
|
||||
*out = make(map[string][]string, len(*in))
|
||||
for key, val := range *in {
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
(*out)[key] = make([]string, len(val))
|
||||
copy((*out)[key], val)
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.UpstreamNameservers != nil {
|
||||
in, out := &in.UpstreamNameservers, &out.UpstreamNameservers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -284,21 +284,26 @@ type LoadBalancerAccessSpec struct {
|
|||
AdditionalSecurityGroups []string `json:"additionalSecurityGroups,omitempty"`
|
||||
}
|
||||
|
||||
// KubeDNSConfig defines the kube dns configuration
|
||||
type KubeDNSConfig struct {
|
||||
// Image is the name of the docker image to run
|
||||
// Deprecated as this is now in the addon
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// Deprecated as this is now in the addon, and controlled by autoscaler
|
||||
Replicas int `json:"replicas,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
ServerIP string `json:"serverIP,omitempty"`
|
||||
// CacheMaxSize is the maximum entries to keep in dnsmaq
|
||||
CacheMaxSize int `json:"cacheMaxSize,omitempty"`
|
||||
// CacheMaxConcurrent is the maximum number of concurrent queries for dnsmasq
|
||||
CacheMaxConcurrent int `json:"cacheMaxConcurrent,omitempty"`
|
||||
// Domain is the dns domain
|
||||
Domain string `json:"domain,omitempty"`
|
||||
// Image is the name of the docker image to run - @deprecated as this is now in the addon
|
||||
Image string `json:"image,omitempty"`
|
||||
// Replicas is the number of pod replicas - @deprecated as this is now in the addon, and controlled by autoscaler
|
||||
Replicas int `json:"replicas,omitempty"`
|
||||
// Provider indicates whether CoreDNS or kube-dns will be the default service discovery.
|
||||
Provider string `json:"provider,omitempty"`
|
||||
// ServerIP is the server ip
|
||||
ServerIP string `json:"serverIP,omitempty"`
|
||||
// StubDomains redirects a domains to another DNS service
|
||||
StubDomains map[string][]string `json:"stubDomains,omitempty"`
|
||||
// UpstreamNameservers sets the upstream nameservers for queries not on the cluster domain
|
||||
UpstreamNameservers []string `json:"upstreamNameservers,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalDNSConfig are options of the dns-controller
|
||||
|
|
|
@ -2357,13 +2357,15 @@ func Convert_kops_KubeControllerManagerConfig_To_v1alpha2_KubeControllerManagerC
|
|||
}
|
||||
|
||||
func autoConvert_v1alpha2_KubeDNSConfig_To_kops_KubeDNSConfig(in *KubeDNSConfig, out *kops.KubeDNSConfig, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Domain = in.Domain
|
||||
out.ServerIP = in.ServerIP
|
||||
out.CacheMaxSize = in.CacheMaxSize
|
||||
out.CacheMaxConcurrent = in.CacheMaxConcurrent
|
||||
out.Domain = in.Domain
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Provider = in.Provider
|
||||
out.ServerIP = in.ServerIP
|
||||
out.StubDomains = in.StubDomains
|
||||
out.UpstreamNameservers = in.UpstreamNameservers
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2373,13 +2375,15 @@ func Convert_v1alpha2_KubeDNSConfig_To_kops_KubeDNSConfig(in *KubeDNSConfig, out
|
|||
}
|
||||
|
||||
func autoConvert_kops_KubeDNSConfig_To_v1alpha2_KubeDNSConfig(in *kops.KubeDNSConfig, out *KubeDNSConfig, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Domain = in.Domain
|
||||
out.ServerIP = in.ServerIP
|
||||
out.CacheMaxSize = in.CacheMaxSize
|
||||
out.CacheMaxConcurrent = in.CacheMaxConcurrent
|
||||
out.Domain = in.Domain
|
||||
out.Image = in.Image
|
||||
out.Replicas = in.Replicas
|
||||
out.Provider = in.Provider
|
||||
out.ServerIP = in.ServerIP
|
||||
out.StubDomains = in.StubDomains
|
||||
out.UpstreamNameservers = in.UpstreamNameservers
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -673,7 +673,7 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
|
|||
*out = nil
|
||||
} else {
|
||||
*out = new(KubeDNSConfig)
|
||||
**out = **in
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.KubeAPIServer != nil {
|
||||
|
@ -2188,6 +2188,23 @@ func (in *KubeControllerManagerConfig) DeepCopy() *KubeControllerManagerConfig {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeDNSConfig) DeepCopyInto(out *KubeDNSConfig) {
|
||||
*out = *in
|
||||
if in.StubDomains != nil {
|
||||
in, out := &in.StubDomains, &out.StubDomains
|
||||
*out = make(map[string][]string, len(*in))
|
||||
for key, val := range *in {
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
(*out)[key] = make([]string, len(val))
|
||||
copy((*out)[key], val)
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.UpstreamNameservers != nil {
|
||||
in, out := &in.UpstreamNameservers, &out.UpstreamNameservers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -267,27 +267,44 @@ func ValidateCluster(c *kops.Cluster, strict bool) *field.Error {
|
|||
}
|
||||
}
|
||||
|
||||
// Check KubeDNS.ServerIP
|
||||
// @check the custom kubedns options are valid
|
||||
if c.Spec.KubeDNS != nil {
|
||||
serverIPString := c.Spec.KubeDNS.ServerIP
|
||||
if serverIPString == "" {
|
||||
return field.Required(fieldSpec.Child("KubeDNS", "ServerIP"), "Cluster did not have KubeDNS.ServerIP set")
|
||||
if c.Spec.KubeDNS.ServerIP != "" {
|
||||
address := c.Spec.KubeDNS.ServerIP
|
||||
ip := net.ParseIP(address)
|
||||
if ip == nil {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "serverIP"), address, "Cluster had an invalid kubeDNS.serverIP")
|
||||
}
|
||||
if !serviceClusterIPRange.Contains(ip) {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "serverIP"), address, fmt.Sprintf("ServiceClusterIPRange %q must contain the DNS Server IP %q", c.Spec.ServiceClusterIPRange, address))
|
||||
}
|
||||
if c.Spec.Kubelet != nil && c.Spec.Kubelet.ClusterDNS != c.Spec.KubeDNS.ServerIP {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "serverIP"), address, "Kubelet ClusterDNS did not match cluster kubeDNS.serverIP")
|
||||
}
|
||||
if c.Spec.MasterKubelet != nil && c.Spec.MasterKubelet.ClusterDNS != c.Spec.KubeDNS.ServerIP {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "serverIP"), address, "MasterKubelet ClusterDNS did not match cluster kubeDNS.serverIP")
|
||||
}
|
||||
}
|
||||
|
||||
dnsServiceIP := net.ParseIP(serverIPString)
|
||||
if dnsServiceIP == nil {
|
||||
return field.Invalid(fieldSpec.Child("KubeDNS", "ServerIP"), serverIPString, "Cluster had an invalid KubeDNS.ServerIP")
|
||||
// @check the nameservers are valid
|
||||
for i, x := range c.Spec.KubeDNS.UpstreamNameservers {
|
||||
if ip := net.ParseIP(x); ip == nil {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "upstreamNameservers").Index(i), x, "Invalid nameserver given, should be a valid ip address")
|
||||
}
|
||||
}
|
||||
|
||||
if !serviceClusterIPRange.Contains(dnsServiceIP) {
|
||||
return field.Invalid(fieldSpec.Child("KubeDNS", "ServerIP"), serverIPString, fmt.Sprintf("ServiceClusterIPRange %q must contain the DNS Server IP %q", c.Spec.ServiceClusterIPRange, serverIPString))
|
||||
}
|
||||
|
||||
if c.Spec.Kubelet != nil && c.Spec.Kubelet.ClusterDNS != c.Spec.KubeDNS.ServerIP {
|
||||
return field.Invalid(fieldSpec.Child("KubeDNS", "ServerIP"), serverIPString, "Kubelet ClusterDNS did not match cluster KubeDNS.ServerIP")
|
||||
}
|
||||
if c.Spec.MasterKubelet != nil && c.Spec.MasterKubelet.ClusterDNS != c.Spec.KubeDNS.ServerIP {
|
||||
return field.Invalid(fieldSpec.Child("KubeDNS", "ServerIP"), serverIPString, "MasterKubelet ClusterDNS did not match cluster KubeDNS.ServerIP")
|
||||
// @check the stubdomain if any
|
||||
if c.Spec.KubeDNS.StubDomains != nil {
|
||||
for domain, nameservers := range c.Spec.KubeDNS.StubDomains {
|
||||
if len(nameservers) <= 0 {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "stubDomains").Key(domain), domain, "No nameservers specified for the stub domain")
|
||||
}
|
||||
for i, x := range nameservers {
|
||||
if ip := net.ParseIP(x); ip == nil {
|
||||
return field.Invalid(fieldSpec.Child("kubeDNS", "stubDomains").Key(domain).Index(i), x, "Invalid nameserver given, should be a valid ip address")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -778,7 +778,7 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
|
|||
*out = nil
|
||||
} else {
|
||||
*out = new(KubeDNSConfig)
|
||||
**out = **in
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.KubeAPIServer != nil {
|
||||
|
@ -2367,6 +2367,23 @@ func (in *KubeControllerManagerConfig) DeepCopy() *KubeControllerManagerConfig {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeDNSConfig) DeepCopyInto(out *KubeDNSConfig) {
|
||||
*out = *in
|
||||
if in.StubDomains != nil {
|
||||
in, out := &in.StubDomains, &out.StubDomains
|
||||
*out = make(map[string][]string, len(*in))
|
||||
for key, val := range *in {
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
(*out)[key] = make([]string, len(val))
|
||||
copy((*out)[key], val)
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.UpstreamNameservers != nil {
|
||||
in, out := &in.UpstreamNameservers, &out.UpstreamNameservers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ type KubeDnsOptionsBuilder struct {
|
|||
|
||||
var _ loader.OptionsBuilder = &KubeDnsOptionsBuilder{}
|
||||
|
||||
// BuildOptions fills in the kubedns model
|
||||
func (b *KubeDnsOptionsBuilder) BuildOptions(o interface{}) error {
|
||||
clusterSpec := o.(*kops.ClusterSpec)
|
||||
|
||||
|
@ -45,12 +46,17 @@ func (b *KubeDnsOptionsBuilder) BuildOptions(o interface{}) error {
|
|||
clusterSpec.KubeDNS.CacheMaxConcurrent = 150
|
||||
}
|
||||
|
||||
ip, err := WellKnownServiceIP(clusterSpec, 10)
|
||||
if err != nil {
|
||||
return err
|
||||
if clusterSpec.KubeDNS.ServerIP == "" {
|
||||
ip, err := WellKnownServiceIP(clusterSpec, 10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clusterSpec.KubeDNS.ServerIP = ip.String()
|
||||
}
|
||||
|
||||
if clusterSpec.KubeDNS.Domain == "" {
|
||||
clusterSpec.KubeDNS.Domain = clusterSpec.ClusterDNSDomain
|
||||
}
|
||||
clusterSpec.KubeDNS.ServerIP = ip.String()
|
||||
clusterSpec.KubeDNS.Domain = clusterSpec.ClusterDNSDomain
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,6 +12,26 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
{{- if or (.KubeDNS.UpstreamNameservers) (.KubeDNS.StubDomains) }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kube-dns
|
||||
namespace: kube-system
|
||||
data:
|
||||
{{- if .KubeDNS.UpstreamNameservers }}
|
||||
upstreamNameservers: |
|
||||
{{ ToJSON .KubeDNS.UpstreamNameservers }}
|
||||
{{- end }}
|
||||
{{- if .KubeDNS.StubDomains }}
|
||||
stubDomains: |
|
||||
{{ ToJSON .KubeDNS.StubDomains }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
---
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
|
@ -126,9 +146,9 @@ spec:
|
|||
initialDelaySeconds: 3
|
||||
timeoutSeconds: 5
|
||||
args:
|
||||
- --domain={{ KubeDNS.Domain }}.
|
||||
- --dns-port=10053
|
||||
- --config-dir=/kube-dns-config
|
||||
- --dns-port=10053
|
||||
- --domain={{ KubeDNS.Domain }}.
|
||||
- --v=2
|
||||
env:
|
||||
- name: PROMETHEUS_PORT
|
||||
|
|
|
@ -28,6 +28,7 @@ When defining a new function:
|
|||
package cloudup
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
@ -59,6 +60,7 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
|
|||
dest["EtcdScheme"] = tf.EtcdScheme
|
||||
dest["SharedVPC"] = tf.SharedVPC
|
||||
dest["UseEtcdTLS"] = tf.UseEtcdTLS
|
||||
dest["ToJSON"] = tf.ToJSON
|
||||
// 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 {
|
||||
|
@ -119,6 +121,16 @@ func (tf *TemplateFunctions) UseEtcdTLS() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// ToJSON returns a json representation of the struct or on error an empty string
|
||||
func (tf *TemplateFunctions) ToJSON(data interface{}) string {
|
||||
encoded, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(encoded)
|
||||
}
|
||||
|
||||
// EtcdScheme parses and grabs the protocol to the etcd cluster
|
||||
func (tf *TemplateFunctions) EtcdScheme() string {
|
||||
if tf.UseEtcdTLS() {
|
||||
|
|
Loading…
Reference in New Issue