Support cloud-config on GCE

This commit is contained in:
Justin Santa Barbara 2017-02-20 12:43:17 -05:00
parent 645f330dad
commit 3d14d07616
21 changed files with 229 additions and 30 deletions

View File

@ -0,0 +1,63 @@
/*
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.
*/
package model
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
"strings"
)
const CloudConfigFilePath = "/etc/kubernetes/cloud.config"
// CloudConfigBuilder creates the cloud configuration file
type CloudConfigBuilder struct {
*NodeupModelContext
}
var _ fi.ModelBuilder = &CloudConfigBuilder{}
func (b *CloudConfigBuilder) Build(c *fi.ModelBuilderContext) error {
// Add cloud config file if needed
var lines []string
cloudConfig := b.Cluster.Spec.CloudConfig
if cloudConfig == nil {
cloudConfig = &kops.CloudConfiguration{}
}
if cloudConfig.NodeTags != nil {
lines = append(lines, "node-tags = "+*cloudConfig.NodeTags)
}
if cloudConfig.NodeInstancePrefix != nil {
lines = append(lines, "node-instance-prefix = "+*cloudConfig.NodeInstancePrefix)
}
if cloudConfig.Multizone != nil {
lines = append(lines, fmt.Sprintf("multizone = %t", *cloudConfig.Multizone))
}
config := "[global]\n" + strings.Join(lines, "\n") + "\n"
t := &nodetasks.File{
Path: CloudConfigFilePath,
Contents: fi.NewStringResource(config),
Type: nodetasks.FileType_File,
}
c.AddTask(t)
return nil
}

View File

@ -69,6 +69,11 @@ func (b *KubeAPIServerBuilder) buildPod() (*v1.Pod, error) {
return nil, fmt.Errorf("error building kube-apiserver flags: %v", err)
}
// Add cloud config file if needed
if b.Cluster.Spec.CloudConfig != nil {
flags += " --cloud-config=" + CloudConfigFilePath
}
redirectCommand := []string{
"/bin/sh", "-c", "/usr/local/bin/kube-apiserver " + flags + " 1>>/var/log/kube-apiserver.log 2>&1",
}
@ -131,6 +136,11 @@ func (b *KubeAPIServerBuilder) buildPod() (*v1.Pod, error) {
addHostPathMapping(pod, container, name, path, true)
}
// Add cloud config file if needed
if b.Cluster.Spec.CloudConfig != nil {
addHostPathMapping(pod, container, "cloudconfig", CloudConfigFilePath, true)
}
if b.Cluster.Spec.KubeAPIServer.PathSrvKubernetes != "" {
addHostPathMapping(pod, container, "srvkube", b.Cluster.Spec.KubeAPIServer.PathSrvKubernetes, true)
}

View File

@ -68,6 +68,11 @@ func (b *KubeControllerManagerBuilder) buildPod() (*v1.Pod, error) {
return nil, fmt.Errorf("error building kube-controller-manager flags: %v", err)
}
// Add cloud config file if needed
if b.Cluster.Spec.CloudConfig != nil {
flags += " --cloud-config=" + CloudConfigFilePath
}
redirectCommand := []string{
"/bin/sh", "-c", "/usr/local/bin/kube-controller-manager " + flags + " 1>>/var/log/kube-controller-manager.log 2>&1",
}
@ -117,6 +122,11 @@ func (b *KubeControllerManagerBuilder) buildPod() (*v1.Pod, error) {
addHostPathMapping(pod, container, name, path, true)
}
// Add cloud config file if needed
if b.Cluster.Spec.CloudConfig != nil {
addHostPathMapping(pod, container, "cloudconfig", CloudConfigFilePath, true)
}
if b.Cluster.Spec.KubeControllerManager.PathSrvKubernetes != "" {
addHostPathMapping(pod, container, "srvkube", b.Cluster.Spec.KubeControllerManager.PathSrvKubernetes, true)
}

View File

@ -48,6 +48,15 @@ func (b *KubeletBuilder) Build(c *fi.ModelBuilderContext) error {
if err != nil {
return fmt.Errorf("error building kubelet flags: %v", err)
}
// Add cloud config file if needed
// We build this flag differently because it depends on CloudConfig, and to expose it directly
// would be a degree of freedom we don't have (we'd have to write the config to different files)
// We can always add this later if it is needed.
if b.Cluster.Spec.CloudConfig != nil {
flags += " --cloud-config=" + CloudConfigFilePath
}
sysconfig := "DAEMON_ARGS=\"" + flags + "\"\n"
t := &nodetasks.File{

View File

@ -231,6 +231,7 @@ type ClusterSpec struct {
KubeProxy *KubeProxyConfig `json:"kubeProxy,omitempty"`
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
MasterKubelet *KubeletConfigSpec `json:"masterKubelet,omitempty"`
CloudConfig *CloudConfiguration `json:"cloudConfig,omitempty"`
// Networking configuration
Networking *NetworkingSpec `json:"networking,omitempty"`

View File

@ -174,8 +174,6 @@ type KubeletConfigSpec struct {
//VolumePluginDir string `json:"volumePluginDir"`
// cloudProvider is the provider for cloud services.
CloudProvider string `json:"cloudProvider,omitempty" flag:"cloud-provider"`
//// cloudConfigFile is the path to the cloud provider configuration file.
//CloudConfigFile string `json:"cloudConfigFile,omitempty"`
// KubeletCgroups is the absolute name of cgroups to isolate the kubelet in.
KubeletCgroups string `json:"kubeletCgroups,omitempty" flag:"kubelet-cgroups"`
// Cgroups that container runtime is expected to be isolated in.
@ -453,8 +451,6 @@ type KubeControllerManagerConfig struct {
//Address string `json:"address"`
// cloudProvider is the provider for cloud services.
CloudProvider string `json:"cloudProvider,omitempty" flag:"cloud-provider"`
//// cloudConfigFile is the path to the cloud provider configuration file.
//CloudConfigFile string `json:"cloudConfigFile"`
//// concurrentEndpointSyncs is the number of endpoint syncing operations
//// that will be done concurrently. Larger number = faster endpoint updating,
//// but more CPU (and network) load.
@ -651,3 +647,10 @@ type LeaderElectionConfiguration struct {
//// leader election is enabled.
//RetryPeriod unversioned.Duration `json:"retryPeriod"`
}
type CloudConfiguration struct {
// GCE cloud-config options
Multizone *bool `json:"multizone,omitempty"`
NodeTags *string `json:"nodeTags,omitempty"`
NodeInstancePrefix *string `json:"nodeInstancePrefix,omitempty"`
}

View File

@ -229,6 +229,7 @@ type ClusterSpec struct {
KubeProxy *KubeProxyConfig `json:"kubeProxy,omitempty"`
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
MasterKubelet *KubeletConfigSpec `json:"masterKubelet,omitempty"`
CloudConfig *CloudConfiguration `json:"cloudConfig,omitempty"`
// Networking configuration
Networking *NetworkingSpec `json:"networking,omitempty"`

View File

@ -173,8 +173,6 @@ type KubeletConfigSpec struct {
//VolumePluginDir string `json:"volumePluginDir"`
// cloudProvider is the provider for cloud services.
CloudProvider string `json:"cloudProvider,omitempty" flag:"cloud-provider"`
//// cloudConfigFile is the path to the cloud provider configuration file.
//CloudConfigFile string `json:"cloudConfigFile,omitempty"`
// KubeletCgroups is the absolute name of cgroups to isolate the kubelet in.
KubeletCgroups string `json:"kubeletCgroups,omitempty" flag:"kubelet-cgroups"`
// Cgroups that container runtime is expected to be isolated in.
@ -449,8 +447,6 @@ type KubeControllerManagerConfig struct {
//Address string `json:"address"`
// cloudProvider is the provider for cloud services.
CloudProvider string `json:"cloudProvider,omitempty" flag:"cloud-provider"`
//// cloudConfigFile is the path to the cloud provider configuration file.
//CloudConfigFile string `json:"cloudConfigFile"`
//// concurrentEndpointSyncs is the number of endpoint syncing operations
//// that will be done concurrently. Larger number = faster endpoint updating,
//// but more CPU (and network) load.
@ -647,3 +643,10 @@ type LeaderElectionConfiguration struct {
//// leader election is enabled.
//RetryPeriod unversioned.Duration `json:"retryPeriod"`
}
type CloudConfiguration struct {
// GCE cloud-config options
Multizone *bool `json:"multizone,omitempty"`
NodeTags *string `json:"nodeTags,omitempty"`
NodeInstancePrefix *string `json:"nodeInstancePrefix,omitempty"`
}

View File

@ -45,6 +45,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_kops_CanalNetworkingSpec_To_v1alpha1_CanalNetworkingSpec,
Convert_v1alpha1_ClassicNetworkingSpec_To_kops_ClassicNetworkingSpec,
Convert_kops_ClassicNetworkingSpec_To_v1alpha1_ClassicNetworkingSpec,
Convert_v1alpha1_CloudConfiguration_To_kops_CloudConfiguration,
Convert_kops_CloudConfiguration_To_v1alpha1_CloudConfiguration,
Convert_v1alpha1_Cluster_To_kops_Cluster,
Convert_kops_Cluster_To_v1alpha1_Cluster,
Convert_v1alpha1_ClusterList_To_kops_ClusterList,
@ -220,6 +222,28 @@ func Convert_kops_ClassicNetworkingSpec_To_v1alpha1_ClassicNetworkingSpec(in *ko
return autoConvert_kops_ClassicNetworkingSpec_To_v1alpha1_ClassicNetworkingSpec(in, out, s)
}
func autoConvert_v1alpha1_CloudConfiguration_To_kops_CloudConfiguration(in *CloudConfiguration, out *kops.CloudConfiguration, s conversion.Scope) error {
out.Multizone = in.Multizone
out.NodeTags = in.NodeTags
out.NodeInstancePrefix = in.NodeInstancePrefix
return nil
}
func Convert_v1alpha1_CloudConfiguration_To_kops_CloudConfiguration(in *CloudConfiguration, out *kops.CloudConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_CloudConfiguration_To_kops_CloudConfiguration(in, out, s)
}
func autoConvert_kops_CloudConfiguration_To_v1alpha1_CloudConfiguration(in *kops.CloudConfiguration, out *CloudConfiguration, s conversion.Scope) error {
out.Multizone = in.Multizone
out.NodeTags = in.NodeTags
out.NodeInstancePrefix = in.NodeInstancePrefix
return nil
}
func Convert_kops_CloudConfiguration_To_v1alpha1_CloudConfiguration(in *kops.CloudConfiguration, out *CloudConfiguration, s conversion.Scope) error {
return autoConvert_kops_CloudConfiguration_To_v1alpha1_CloudConfiguration(in, out, s)
}
func autoConvert_v1alpha1_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s conversion.Scope) error {
if err := api.Convert_v1_TypeMeta_To_v1_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
@ -418,6 +442,15 @@ func autoConvert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
} else {
out.MasterKubelet = nil
}
if in.CloudConfig != nil {
in, out := &in.CloudConfig, &out.CloudConfig
*out = new(kops.CloudConfiguration)
if err := Convert_v1alpha1_CloudConfiguration_To_kops_CloudConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.CloudConfig = nil
}
if in.Networking != nil {
in, out := &in.Networking, &out.Networking
*out = new(kops.NetworkingSpec)
@ -556,6 +589,15 @@ func autoConvert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in *kops.ClusterSpec,
} else {
out.MasterKubelet = nil
}
if in.CloudConfig != nil {
in, out := &in.CloudConfig, &out.CloudConfig
*out = new(CloudConfiguration)
if err := Convert_kops_CloudConfiguration_To_v1alpha1_CloudConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.CloudConfig = nil
}
if in.Networking != nil {
in, out := &in.Networking, &out.Networking
*out = new(NetworkingSpec)

View File

@ -149,6 +149,7 @@ type ClusterSpec struct {
KubeProxy *KubeProxyConfig `json:"kubeProxy,omitempty"`
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
MasterKubelet *KubeletConfigSpec `json:"masterKubelet,omitempty"`
CloudConfig *CloudConfiguration `json:"cloudConfig,omitempty"`
// Networking configuration
Networking *NetworkingSpec `json:"networking,omitempty"`

View File

@ -269,3 +269,10 @@ type LeaderElectionConfiguration struct {
// components for high availability.
LeaderElect *bool `json:"leaderElect,omitempty" flag:"leader-elect"`
}
type CloudConfiguration struct {
// GCE cloud-config options
Multizone *bool `json:"multizone,omitempty"`
NodeTags *string `json:"nodeTags,omitempty"`
NodeInstancePrefix *string `json:"nodeInstancePrefix,omitempty"`
}

View File

@ -47,6 +47,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_kops_CanalNetworkingSpec_To_v1alpha2_CanalNetworkingSpec,
Convert_v1alpha2_ClassicNetworkingSpec_To_kops_ClassicNetworkingSpec,
Convert_kops_ClassicNetworkingSpec_To_v1alpha2_ClassicNetworkingSpec,
Convert_v1alpha2_CloudConfiguration_To_kops_CloudConfiguration,
Convert_kops_CloudConfiguration_To_v1alpha2_CloudConfiguration,
Convert_v1alpha2_Cluster_To_kops_Cluster,
Convert_kops_Cluster_To_v1alpha2_Cluster,
Convert_v1alpha2_ClusterList_To_kops_ClusterList,
@ -246,6 +248,28 @@ func Convert_kops_ClassicNetworkingSpec_To_v1alpha2_ClassicNetworkingSpec(in *ko
return autoConvert_kops_ClassicNetworkingSpec_To_v1alpha2_ClassicNetworkingSpec(in, out, s)
}
func autoConvert_v1alpha2_CloudConfiguration_To_kops_CloudConfiguration(in *CloudConfiguration, out *kops.CloudConfiguration, s conversion.Scope) error {
out.Multizone = in.Multizone
out.NodeTags = in.NodeTags
out.NodeInstancePrefix = in.NodeInstancePrefix
return nil
}
func Convert_v1alpha2_CloudConfiguration_To_kops_CloudConfiguration(in *CloudConfiguration, out *kops.CloudConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha2_CloudConfiguration_To_kops_CloudConfiguration(in, out, s)
}
func autoConvert_kops_CloudConfiguration_To_v1alpha2_CloudConfiguration(in *kops.CloudConfiguration, out *CloudConfiguration, s conversion.Scope) error {
out.Multizone = in.Multizone
out.NodeTags = in.NodeTags
out.NodeInstancePrefix = in.NodeInstancePrefix
return nil
}
func Convert_kops_CloudConfiguration_To_v1alpha2_CloudConfiguration(in *kops.CloudConfiguration, out *CloudConfiguration, s conversion.Scope) error {
return autoConvert_kops_CloudConfiguration_To_v1alpha2_CloudConfiguration(in, out, s)
}
func autoConvert_v1alpha2_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s conversion.Scope) error {
if err := api.Convert_v1_TypeMeta_To_v1_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
@ -454,6 +478,15 @@ func autoConvert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
} else {
out.MasterKubelet = nil
}
if in.CloudConfig != nil {
in, out := &in.CloudConfig, &out.CloudConfig
*out = new(kops.CloudConfiguration)
if err := Convert_v1alpha2_CloudConfiguration_To_kops_CloudConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.CloudConfig = nil
}
if in.Networking != nil {
in, out := &in.Networking, &out.Networking
*out = new(kops.NetworkingSpec)
@ -606,6 +639,15 @@ func autoConvert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(in *kops.ClusterSpec,
} else {
out.MasterKubelet = nil
}
if in.CloudConfig != nil {
in, out := &in.CloudConfig, &out.CloudConfig
*out = new(CloudConfiguration)
if err := Convert_kops_CloudConfiguration_To_v1alpha2_CloudConfiguration(*in, *out, s); err != nil {
return err
}
} else {
out.CloudConfig = nil
}
if in.Networking != nil {
in, out := &in.Networking, &out.Networking
*out = new(NetworkingSpec)

View File

@ -23,11 +23,11 @@ import (
"github.com/golang/glog"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kops/util/pkg/vfs"
"math/big"
"net"
"strings"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
)
// OptionsContext is the context object for options builders

View File

@ -148,6 +148,12 @@ func (b *KubeletOptionsBuilder) BuildOptions(o interface{}) error {
if cloudProvider == fi.CloudProviderGCE {
clusterSpec.Kubelet.CloudProvider = "gce"
clusterSpec.Kubelet.HairpinMode = "promiscuous-bridge"
if clusterSpec.CloudConfig == nil {
clusterSpec.CloudConfig = &kops.CloudConfiguration{}
}
clusterSpec.CloudConfig.Multizone = fi.Bool(true)
clusterSpec.CloudConfig.NodeTags = fi.String(GCETagForRole(b.Context.ClusterName, kops.InstanceGroupRoleNode))
}
usesKubenet, err := UsesKubenet(clusterSpec)

View File

@ -17,11 +17,11 @@ limitations under the License.
package gcemodel
import (
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/model"
"k8s.io/kops/pkg/model/components"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kops/upup/pkg/fi/cloudup/gcetasks"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/model/components"
)
type GCEModelContext struct {

View File

@ -18,9 +18,9 @@ package gcemodel
import (
"github.com/golang/glog"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/gcetasks"
"k8s.io/kops/pkg/apis/kops"
)
// ExternalAccessModelBuilder configures security group rules for external access

View File

@ -18,9 +18,9 @@ package gcemodel
import (
"github.com/golang/glog"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/gcetasks"
"k8s.io/kops/pkg/apis/kops"
)
// FirewallModelBuilder configures firewall network objects
@ -48,8 +48,8 @@ func (b *FirewallModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow all traffic from nodes -> nodes
{
t := &gcetasks.FirewallRule{
Name: s(b.SafeObjectName("node-to-node")),
Network: b.LinkToNetwork(),
Name: s(b.SafeObjectName("node-to-node")),
Network: b.LinkToNetwork(),
SourceTags: []string{b.GCETagForRole(kops.InstanceGroupRoleNode)},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleNode)},
Allowed: []string{"tcp", "udp", "icmp", "esp", "ah", "sctp"},
@ -66,8 +66,8 @@ func (b *FirewallModelBuilder) Build(c *fi.ModelBuilderContext) error {
Name: s(b.SafeObjectName("cidr-to-node")),
Network: b.LinkToNetwork(),
SourceRanges: []string{b.Cluster.Spec.NonMasqueradeCIDR},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleNode)},
Allowed: []string{"tcp", "udp", "icmp", "esp", "ah", "sctp"},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleNode)},
Allowed: []string{"tcp", "udp", "icmp", "esp", "ah", "sctp"},
}
c.AddTask(t)
}
@ -75,8 +75,8 @@ func (b *FirewallModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow full traffic from master -> master
{
t := &gcetasks.FirewallRule{
Name: s(b.SafeObjectName("master-to-master")),
Network: b.LinkToNetwork(),
Name: s(b.SafeObjectName("master-to-master")),
Network: b.LinkToNetwork(),
SourceTags: []string{b.GCETagForRole(kops.InstanceGroupRoleMaster)},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleMaster)},
Allowed: []string{"tcp", "udp", "icmp", "esp", "ah", "sctp"},
@ -87,8 +87,8 @@ func (b *FirewallModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow full traffic from master -> node
{
t := &gcetasks.FirewallRule{
Name: s(b.SafeObjectName("master-to-node")),
Network: b.LinkToNetwork(),
Name: s(b.SafeObjectName("master-to-node")),
Network: b.LinkToNetwork(),
SourceTags: []string{b.GCETagForRole(kops.InstanceGroupRoleMaster)},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleNode)},
Allowed: []string{"tcp", "udp", "icmp", "esp", "ah", "sctp"},
@ -99,8 +99,8 @@ func (b *FirewallModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow limited traffic from nodes -> masters
{
t := &gcetasks.FirewallRule{
Name: s(b.SafeObjectName("node-to-master")),
Network: b.LinkToNetwork(),
Name: s(b.SafeObjectName("node-to-master")),
Network: b.LinkToNetwork(),
SourceTags: []string{b.GCETagForRole(kops.InstanceGroupRoleNode)},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleMaster)},
Allowed: []string{"tcp:443", "tcp:4194"},
@ -115,8 +115,8 @@ func (b *FirewallModelBuilder) Build(c *fi.ModelBuilderContext) error {
Name: s(b.SafeObjectName("cidr-to-master")),
Network: b.LinkToNetwork(),
SourceRanges: []string{b.Cluster.Spec.NonMasqueradeCIDR},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleMaster)},
Allowed: []string{"tcp:443", "tcp:4194"},
TargetTags: []string{b.GCETagForRole(kops.InstanceGroupRoleMaster)},
Allowed: []string{"tcp:443", "tcp:4194"},
}
c.AddTask(t)
}

View File

@ -30,6 +30,7 @@ import (
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/pkg/apis/kops/validation"
"k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/model"
"k8s.io/kops/pkg/model/awsmodel"
"k8s.io/kops/pkg/model/components"
@ -46,7 +47,6 @@ import (
"k8s.io/kops/util/pkg/hashing"
"k8s.io/kops/util/pkg/vfs"
k8sapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kops/pkg/featureflag"
)
const DefaultMaxTaskDuration = 10 * time.Minute

View File

@ -29,9 +29,9 @@ import (
// InstanceTemplate represents a GCE InstanceTemplate
//go:generate fitask -type=InstanceTemplate
type InstanceTemplate struct {
Name *string
Network *Network
Tags []string
Name *string
Network *Network
Tags []string
//Labels map[string]string
Preemptible *bool

View File

@ -208,6 +208,7 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
loader := NewLoader(c.config, c.cluster, assets, nodeTags)
loader.Builders = append(loader.Builders, &model.DockerBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &model.CloudConfigBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &model.KubeletBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &model.KubectlBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &model.EtcdBuilder{NodeupModelContext: modelContext})

View File

@ -145,7 +145,7 @@ func (p *GSPath) ReadFile() ([]byte, error) {
return nil, fmt.Errorf("error reading %s: %v", p, err)
}
if response == nil {
return nil, fmt.Errorf("no response returned from: %v", p, err)
return nil, fmt.Errorf("no response returned from reading %s", p)
}
defer response.Body.Close()