diff --git a/docs/cluster_spec.md b/docs/cluster_spec.md index 66f5131c5f..ac2215ef1b 100644 --- a/docs/cluster_spec.md +++ b/docs/cluster_spec.md @@ -439,3 +439,15 @@ Providing the name of a key already in AWS is an alternative to `--ssh-public-ke spec: sshKeyName: myexistingkey ``` + +### target + +In some use-cases you may wish to augment the target output with extra options. `target` supports a minimal amount of options you can do this with. Currently only the terraform target supports this, but if other use cases present themselves, kops may eventually support more. + +```yaml +spec: + target: + terraform: + providerExtraConfig: + alias: foo +``` \ No newline at end of file diff --git a/pkg/apis/kops/cluster.go b/pkg/apis/kops/cluster.go index d930e9f62d..70e8f324a0 100644 --- a/pkg/apis/kops/cluster.go +++ b/pkg/apis/kops/cluster.go @@ -160,6 +160,8 @@ type ClusterSpec struct { IAM *IAMSpec `json:"iam,omitempty"` // EncryptionConfig controls if encryption is enabled EncryptionConfig *bool `json:"encryptionConfig,omitempty"` + // Target allows for us to nest extra config for targets such as terraform + Target *TargetSpec `json:"target,omitempty"` } // FileAssetSpec defines the structure for a file asset @@ -375,6 +377,25 @@ type HTTPProxy struct { // Password string `json:"password,omitempty"` } +// TargetSpec allows for specifying target config in an extensible way +type TargetSpec struct { + Terraform *TerraformSpec `json:"terraform,omitempty"` +} + +func (t *TargetSpec) IsEmpty() bool { + return t.Terraform == nil +} + +// TerraformSpec allows us to specify terraform config in an extensible way +type TerraformSpec struct { + // ProviderExtraConfig contains key/value pairs to add to the rendered terraform "provider" block + ProviderExtraConfig *map[string]string `json:"providerExtraConfig,omitempty"` +} + +func (t *TerraformSpec) IsEmpty() bool { + return t.ProviderExtraConfig == nil +} + // FillDefaults populates default values. // This is different from PerformAssignments, because these values are changeable, and thus we don't need to // store them (i.e. we don't need to 'lock them') diff --git a/pkg/apis/kops/v1alpha1/cluster.go b/pkg/apis/kops/v1alpha1/cluster.go index eb0d9019f0..253f362954 100644 --- a/pkg/apis/kops/v1alpha1/cluster.go +++ b/pkg/apis/kops/v1alpha1/cluster.go @@ -159,6 +159,8 @@ type ClusterSpec struct { IAM *IAMSpec `json:"iam,omitempty"` // EncryptionConfig holds the encryption config EncryptionConfig *bool `json:"encryptionConfig,omitempty"` + // Target allows for us to nest extra config for targets such as terraform + Target *TargetSpec `json:"target,omitempty"` } // FileAssetSpec defines the structure for a file asset @@ -361,3 +363,22 @@ type HTTPProxy struct { // User string `json:"user,omitempty"` // Password string `json:"password,omitempty"` } + +// TargetSpec allows for specifying target config in an extensible way +type TargetSpec struct { + Terraform *TerraformSpec `json:"terraform,omitempty"` +} + +func (t *TargetSpec) IsEmpty() bool { + return t.Terraform == nil +} + +// TerraformSpec allows us to specify terraform config in an extensible way +type TerraformSpec struct { + // ProviderExtraConfig contains key/value pairs to add to the rendered terraform "provider" block + ProviderExtraConfig *map[string]string `json:"providerExtraConfig,omitempty"` +} + +func (t *TerraformSpec) IsEmpty() bool { + return t.ProviderExtraConfig == nil +} diff --git a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go index e6583a89fb..8594d40c77 100644 --- a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go @@ -141,6 +141,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kops_SSHCredentialList_To_v1alpha1_SSHCredentialList, Convert_v1alpha1_SSHCredentialSpec_To_kops_SSHCredentialSpec, Convert_kops_SSHCredentialSpec_To_v1alpha1_SSHCredentialSpec, + Convert_v1alpha1_TargetSpec_To_kops_TargetSpec, + Convert_kops_TargetSpec_To_v1alpha1_TargetSpec, + Convert_v1alpha1_TerraformSpec_To_kops_TerraformSpec, + Convert_kops_TerraformSpec_To_v1alpha1_TerraformSpec, Convert_v1alpha1_UserData_To_kops_UserData, Convert_kops_UserData_To_v1alpha1_UserData, Convert_v1alpha1_WeaveNetworkingSpec_To_kops_WeaveNetworkingSpec, @@ -833,6 +837,15 @@ func autoConvert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out * out.IAM = nil } out.EncryptionConfig = in.EncryptionConfig + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = new(kops.TargetSpec) + if err := Convert_v1alpha1_TargetSpec_To_kops_TargetSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Target = nil + } return nil } @@ -1070,6 +1083,15 @@ func autoConvert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in *kops.ClusterSpec, out.IAM = nil } out.EncryptionConfig = in.EncryptionConfig + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = new(TargetSpec) + if err := Convert_kops_TargetSpec_To_v1alpha1_TargetSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Target = nil + } return nil } @@ -2698,6 +2720,62 @@ func Convert_kops_SSHCredentialSpec_To_v1alpha1_SSHCredentialSpec(in *kops.SSHCr return autoConvert_kops_SSHCredentialSpec_To_v1alpha1_SSHCredentialSpec(in, out, s) } +func autoConvert_v1alpha1_TargetSpec_To_kops_TargetSpec(in *TargetSpec, out *kops.TargetSpec, s conversion.Scope) error { + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + *out = new(kops.TerraformSpec) + if err := Convert_v1alpha1_TerraformSpec_To_kops_TerraformSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Terraform = nil + } + return nil +} + +// Convert_v1alpha1_TargetSpec_To_kops_TargetSpec is an autogenerated conversion function. +func Convert_v1alpha1_TargetSpec_To_kops_TargetSpec(in *TargetSpec, out *kops.TargetSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_TargetSpec_To_kops_TargetSpec(in, out, s) +} + +func autoConvert_kops_TargetSpec_To_v1alpha1_TargetSpec(in *kops.TargetSpec, out *TargetSpec, s conversion.Scope) error { + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + *out = new(TerraformSpec) + if err := Convert_kops_TerraformSpec_To_v1alpha1_TerraformSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Terraform = nil + } + return nil +} + +// Convert_kops_TargetSpec_To_v1alpha1_TargetSpec is an autogenerated conversion function. +func Convert_kops_TargetSpec_To_v1alpha1_TargetSpec(in *kops.TargetSpec, out *TargetSpec, s conversion.Scope) error { + return autoConvert_kops_TargetSpec_To_v1alpha1_TargetSpec(in, out, s) +} + +func autoConvert_v1alpha1_TerraformSpec_To_kops_TerraformSpec(in *TerraformSpec, out *kops.TerraformSpec, s conversion.Scope) error { + out.ProviderExtraConfig = in.ProviderExtraConfig + return nil +} + +// Convert_v1alpha1_TerraformSpec_To_kops_TerraformSpec is an autogenerated conversion function. +func Convert_v1alpha1_TerraformSpec_To_kops_TerraformSpec(in *TerraformSpec, out *kops.TerraformSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_TerraformSpec_To_kops_TerraformSpec(in, out, s) +} + +func autoConvert_kops_TerraformSpec_To_v1alpha1_TerraformSpec(in *kops.TerraformSpec, out *TerraformSpec, s conversion.Scope) error { + out.ProviderExtraConfig = in.ProviderExtraConfig + return nil +} + +// Convert_kops_TerraformSpec_To_v1alpha1_TerraformSpec is an autogenerated conversion function. +func Convert_kops_TerraformSpec_To_v1alpha1_TerraformSpec(in *kops.TerraformSpec, out *TerraformSpec, s conversion.Scope) error { + return autoConvert_kops_TerraformSpec_To_v1alpha1_TerraformSpec(in, out, s) +} + func autoConvert_v1alpha1_UserData_To_kops_UserData(in *UserData, out *kops.UserData, s conversion.Scope) error { out.Name = in.Name out.Type = in.Type diff --git a/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go index 158998565a..7bf24c60b6 100644 --- a/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go @@ -21,11 +21,10 @@ limitations under the License. package v1alpha1 import ( - reflect "reflect" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + reflect "reflect" ) func init() { @@ -258,6 +257,14 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { in.(*SSHCredentialSpec).DeepCopyInto(out.(*SSHCredentialSpec)) return nil }, InType: reflect.TypeOf(&SSHCredentialSpec{})}, + conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TargetSpec).DeepCopyInto(out.(*TargetSpec)) + return nil + }, InType: reflect.TypeOf(&TargetSpec{})}, + conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TerraformSpec).DeepCopyInto(out.(*TerraformSpec)) + return nil + }, InType: reflect.TypeOf(&TerraformSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { in.(*TopologySpec).DeepCopyInto(out.(*TopologySpec)) return nil @@ -1044,6 +1051,15 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { **out = **in } } + if in.Target != nil { + in, out := &in.Target, &out.Target + if *in == nil { + *out = nil + } else { + *out = new(TargetSpec) + (*in).DeepCopyInto(*out) + } + } return } @@ -2939,6 +2955,62 @@ func (in *SSHCredentialSpec) DeepCopy() *SSHCredentialSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetSpec) DeepCopyInto(out *TargetSpec) { + *out = *in + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + if *in == nil { + *out = nil + } else { + *out = new(TerraformSpec) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetSpec. +func (in *TargetSpec) DeepCopy() *TargetSpec { + if in == nil { + return nil + } + out := new(TargetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TerraformSpec) DeepCopyInto(out *TerraformSpec) { + *out = *in + if in.ProviderExtraConfig != nil { + in, out := &in.ProviderExtraConfig, &out.ProviderExtraConfig + if *in == nil { + *out = nil + } else { + *out = new(map[string]string) + if **in != nil { + in, out := *in, *out + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerraformSpec. +func (in *TerraformSpec) DeepCopy() *TerraformSpec { + if in == nil { + return nil + } + out := new(TerraformSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TopologySpec) DeepCopyInto(out *TopologySpec) { *out = *in diff --git a/pkg/apis/kops/v1alpha2/cluster.go b/pkg/apis/kops/v1alpha2/cluster.go index 385ac7a0c3..6bf220a8a1 100644 --- a/pkg/apis/kops/v1alpha2/cluster.go +++ b/pkg/apis/kops/v1alpha2/cluster.go @@ -160,6 +160,8 @@ type ClusterSpec struct { IAM *IAMSpec `json:"iam,omitempty"` // EncryptionConfig holds the encryption config EncryptionConfig *bool `json:"encryptionConfig,omitempty"` + // Target allows for us to nest extra config for targets such as terraform + Target *TargetSpec `json:"target,omitempty"` } // FileAssetSpec defines the structure for a file asset @@ -370,3 +372,22 @@ type HTTPProxy struct { // User string `json:"user,omitempty"` // Password string `json:"password,omitempty"` } + +// TargetSpec allows for specifying target config in an extensible way +type TargetSpec struct { + Terraform *TerraformSpec `json:"terraform,omitempty"` +} + +func (t *TargetSpec) IsEmpty() bool { + return t.Terraform == nil +} + +// TerraformSpec allows us to specify terraform config in an extensible way +type TerraformSpec struct { + // ProviderExtraConfig contains key/value pairs to add to the rendered terraform "provider" block + ProviderExtraConfig *map[string]string `json:"providerExtraConfig,omitempty"` +} + +func (t *TerraformSpec) IsEmpty() bool { + return t.ProviderExtraConfig == nil +} diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go index 3c86d11ec5..431950361d 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go @@ -153,6 +153,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kops_SSHCredentialList_To_v1alpha2_SSHCredentialList, Convert_v1alpha2_SSHCredentialSpec_To_kops_SSHCredentialSpec, Convert_kops_SSHCredentialSpec_To_v1alpha2_SSHCredentialSpec, + Convert_v1alpha2_TargetSpec_To_kops_TargetSpec, + Convert_kops_TargetSpec_To_v1alpha2_TargetSpec, + Convert_v1alpha2_TerraformSpec_To_kops_TerraformSpec, + Convert_kops_TerraformSpec_To_v1alpha2_TerraformSpec, Convert_v1alpha2_TopologySpec_To_kops_TopologySpec, Convert_kops_TopologySpec_To_v1alpha2_TopologySpec, Convert_v1alpha2_UserData_To_kops_UserData, @@ -880,6 +884,15 @@ func autoConvert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out * out.IAM = nil } out.EncryptionConfig = in.EncryptionConfig + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = new(kops.TargetSpec) + if err := Convert_v1alpha2_TargetSpec_To_kops_TargetSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Target = nil + } return nil } @@ -1132,6 +1145,15 @@ func autoConvert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(in *kops.ClusterSpec, out.IAM = nil } out.EncryptionConfig = in.EncryptionConfig + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = new(TargetSpec) + if err := Convert_kops_TargetSpec_To_v1alpha2_TargetSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Target = nil + } return nil } @@ -2960,6 +2982,62 @@ func Convert_kops_SSHCredentialSpec_To_v1alpha2_SSHCredentialSpec(in *kops.SSHCr return autoConvert_kops_SSHCredentialSpec_To_v1alpha2_SSHCredentialSpec(in, out, s) } +func autoConvert_v1alpha2_TargetSpec_To_kops_TargetSpec(in *TargetSpec, out *kops.TargetSpec, s conversion.Scope) error { + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + *out = new(kops.TerraformSpec) + if err := Convert_v1alpha2_TerraformSpec_To_kops_TerraformSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Terraform = nil + } + return nil +} + +// Convert_v1alpha2_TargetSpec_To_kops_TargetSpec is an autogenerated conversion function. +func Convert_v1alpha2_TargetSpec_To_kops_TargetSpec(in *TargetSpec, out *kops.TargetSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_TargetSpec_To_kops_TargetSpec(in, out, s) +} + +func autoConvert_kops_TargetSpec_To_v1alpha2_TargetSpec(in *kops.TargetSpec, out *TargetSpec, s conversion.Scope) error { + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + *out = new(TerraformSpec) + if err := Convert_kops_TerraformSpec_To_v1alpha2_TerraformSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Terraform = nil + } + return nil +} + +// Convert_kops_TargetSpec_To_v1alpha2_TargetSpec is an autogenerated conversion function. +func Convert_kops_TargetSpec_To_v1alpha2_TargetSpec(in *kops.TargetSpec, out *TargetSpec, s conversion.Scope) error { + return autoConvert_kops_TargetSpec_To_v1alpha2_TargetSpec(in, out, s) +} + +func autoConvert_v1alpha2_TerraformSpec_To_kops_TerraformSpec(in *TerraformSpec, out *kops.TerraformSpec, s conversion.Scope) error { + out.ProviderExtraConfig = in.ProviderExtraConfig + return nil +} + +// Convert_v1alpha2_TerraformSpec_To_kops_TerraformSpec is an autogenerated conversion function. +func Convert_v1alpha2_TerraformSpec_To_kops_TerraformSpec(in *TerraformSpec, out *kops.TerraformSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_TerraformSpec_To_kops_TerraformSpec(in, out, s) +} + +func autoConvert_kops_TerraformSpec_To_v1alpha2_TerraformSpec(in *kops.TerraformSpec, out *TerraformSpec, s conversion.Scope) error { + out.ProviderExtraConfig = in.ProviderExtraConfig + return nil +} + +// Convert_kops_TerraformSpec_To_v1alpha2_TerraformSpec is an autogenerated conversion function. +func Convert_kops_TerraformSpec_To_v1alpha2_TerraformSpec(in *kops.TerraformSpec, out *TerraformSpec, s conversion.Scope) error { + return autoConvert_kops_TerraformSpec_To_v1alpha2_TerraformSpec(in, out, s) +} + func autoConvert_v1alpha2_TopologySpec_To_kops_TopologySpec(in *TopologySpec, out *kops.TopologySpec, s conversion.Scope) error { out.Masters = in.Masters out.Nodes = in.Nodes diff --git a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go index ccb7490b93..6356ebb2a5 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go @@ -21,11 +21,10 @@ limitations under the License. package v1alpha2 import ( - reflect "reflect" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + reflect "reflect" ) func init() { @@ -274,6 +273,14 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { in.(*SSHCredentialSpec).DeepCopyInto(out.(*SSHCredentialSpec)) return nil }, InType: reflect.TypeOf(&SSHCredentialSpec{})}, + conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TargetSpec).DeepCopyInto(out.(*TargetSpec)) + return nil + }, InType: reflect.TypeOf(&TargetSpec{})}, + conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TerraformSpec).DeepCopyInto(out.(*TerraformSpec)) + return nil + }, InType: reflect.TypeOf(&TerraformSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { in.(*TopologySpec).DeepCopyInto(out.(*TopologySpec)) return nil @@ -1054,6 +1061,15 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { **out = **in } } + if in.Target != nil { + in, out := &in.Target, &out.Target + if *in == nil { + *out = nil + } else { + *out = new(TargetSpec) + (*in).DeepCopyInto(*out) + } + } return } @@ -3065,6 +3081,62 @@ func (in *SSHCredentialSpec) DeepCopy() *SSHCredentialSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetSpec) DeepCopyInto(out *TargetSpec) { + *out = *in + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + if *in == nil { + *out = nil + } else { + *out = new(TerraformSpec) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetSpec. +func (in *TargetSpec) DeepCopy() *TargetSpec { + if in == nil { + return nil + } + out := new(TargetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TerraformSpec) DeepCopyInto(out *TerraformSpec) { + *out = *in + if in.ProviderExtraConfig != nil { + in, out := &in.ProviderExtraConfig, &out.ProviderExtraConfig + if *in == nil { + *out = nil + } else { + *out = new(map[string]string) + if **in != nil { + in, out := *in, *out + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerraformSpec. +func (in *TerraformSpec) DeepCopy() *TerraformSpec { + if in == nil { + return nil + } + out := new(TerraformSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TopologySpec) DeepCopyInto(out *TopologySpec) { *out = *in diff --git a/pkg/apis/kops/zz_generated.deepcopy.go b/pkg/apis/kops/zz_generated.deepcopy.go index b6bf774163..43c09199b4 100644 --- a/pkg/apis/kops/zz_generated.deepcopy.go +++ b/pkg/apis/kops/zz_generated.deepcopy.go @@ -21,11 +21,10 @@ limitations under the License. package kops import ( - reflect "reflect" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + reflect "reflect" ) func init() { @@ -314,6 +313,14 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { in.(*SSHCredentialSpec).DeepCopyInto(out.(*SSHCredentialSpec)) return nil }, InType: reflect.TypeOf(&SSHCredentialSpec{})}, + conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TargetSpec).DeepCopyInto(out.(*TargetSpec)) + return nil + }, InType: reflect.TypeOf(&TargetSpec{})}, + conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TerraformSpec).DeepCopyInto(out.(*TerraformSpec)) + return nil + }, InType: reflect.TypeOf(&TerraformSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { in.(*TopologySpec).DeepCopyInto(out.(*TopologySpec)) return nil @@ -1199,6 +1206,15 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { **out = **in } } + if in.Target != nil { + in, out := &in.Target, &out.Target + if *in == nil { + *out = nil + } else { + *out = new(TargetSpec) + (*in).DeepCopyInto(*out) + } + } return } @@ -3316,6 +3332,62 @@ func (in *SSHCredentialSpec) DeepCopy() *SSHCredentialSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetSpec) DeepCopyInto(out *TargetSpec) { + *out = *in + if in.Terraform != nil { + in, out := &in.Terraform, &out.Terraform + if *in == nil { + *out = nil + } else { + *out = new(TerraformSpec) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetSpec. +func (in *TargetSpec) DeepCopy() *TargetSpec { + if in == nil { + return nil + } + out := new(TargetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TerraformSpec) DeepCopyInto(out *TerraformSpec) { + *out = *in + if in.ProviderExtraConfig != nil { + in, out := &in.ProviderExtraConfig, &out.ProviderExtraConfig + if *in == nil { + *out = nil + } else { + *out = new(map[string]string) + if **in != nil { + in, out := *in, *out + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerraformSpec. +func (in *TerraformSpec) DeepCopy() *TerraformSpec { + if in == nil { + return nil + } + out := new(TerraformSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TopologySpec) DeepCopyInto(out *TopologySpec) { *out = *in diff --git a/pkg/client/clientset_generated/clientset/scheme/register.go b/pkg/client/clientset_generated/clientset/scheme/register.go index 3d4d4a981f..cc01994808 100644 --- a/pkg/client/clientset_generated/clientset/scheme/register.go +++ b/pkg/client/clientset_generated/clientset/scheme/register.go @@ -17,8 +17,6 @@ limitations under the License. package scheme import ( - os "os" - announced "k8s.io/apimachinery/pkg/apimachinery/announced" registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -26,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" kops "k8s.io/kops/pkg/apis/kops/install" + os "os" ) var Scheme = runtime.NewScheme() diff --git a/pkg/client/clientset_generated/internalclientset/scheme/register.go b/pkg/client/clientset_generated/internalclientset/scheme/register.go index 3d4d4a981f..cc01994808 100644 --- a/pkg/client/clientset_generated/internalclientset/scheme/register.go +++ b/pkg/client/clientset_generated/internalclientset/scheme/register.go @@ -17,8 +17,6 @@ limitations under the License. package scheme import ( - os "os" - announced "k8s.io/apimachinery/pkg/apimachinery/announced" registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -26,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" kops "k8s.io/kops/pkg/apis/kops/install" + os "os" ) var Scheme = runtime.NewScheme() diff --git a/upup/pkg/fi/cloudup/apply_cluster.go b/upup/pkg/fi/cloudup/apply_cluster.go index e7c4d54ad3..efd2fd4e07 100644 --- a/upup/pkg/fi/cloudup/apply_cluster.go +++ b/upup/pkg/fi/cloudup/apply_cluster.go @@ -659,7 +659,7 @@ func (c *ApplyClusterCmd) Run() error { case TargetTerraform: checkExisting = false outDir := c.OutDir - tf := terraform.NewTerraformTarget(cloud, region, project, outDir) + tf := terraform.NewTerraformTarget(cloud, region, project, outDir, cluster.Spec.Target) // We include a few "util" variables in the TF output if err := tf.AddOutputVariable("region", terraform.LiteralFromStringValue(region)); err != nil { diff --git a/upup/pkg/fi/cloudup/terraform/target.go b/upup/pkg/fi/cloudup/terraform/target.go index 46fae3839f..8553eca89b 100644 --- a/upup/pkg/fi/cloudup/terraform/target.go +++ b/upup/pkg/fi/cloudup/terraform/target.go @@ -48,17 +48,20 @@ type TerraformTarget struct { outputs map[string]*terraformOutputVariable // files is a map of TF resource files that should be created files map[string][]byte + // extra config to add to the provider block + clusterSpecTarget *kops.TargetSpec } -func NewTerraformTarget(cloud fi.Cloud, region, project string, outDir string) *TerraformTarget { +func NewTerraformTarget(cloud fi.Cloud, region, project string, outDir string, clusterSpecTarget *kops.TargetSpec) *TerraformTarget { return &TerraformTarget{ Cloud: cloud, Region: region, Project: project, - outDir: outDir, - files: make(map[string][]byte), - outputs: make(map[string]*terraformOutputVariable), + outDir: outDir, + files: make(map[string][]byte), + outputs: make(map[string]*terraformOutputVariable), + clusterSpecTarget: clusterSpecTarget, } } @@ -158,6 +161,16 @@ func (t *TerraformTarget) AddOutputVariableArray(key string, literal *Literal) e return nil } +// tfGetProviderExtraConfig is a helper function to get extra config with safety checks on the pointers. +func tfGetProviderExtraConfig(c *kops.TargetSpec) map[string]string { + if c != nil && + c.Terraform != nil && + c.Terraform.ProviderExtraConfig != nil { + return *c.Terraform.ProviderExtraConfig + } + return nil +} + func (t *TerraformTarget) Finish(taskMap map[string]fi.Task) error { resourcesByType := make(map[string]map[string]interface{}) @@ -182,14 +195,23 @@ func (t *TerraformTarget) Finish(taskMap map[string]fi.Task) error { providerGoogle := make(map[string]interface{}) providerGoogle["project"] = t.Project providerGoogle["region"] = t.Region + for k, v := range tfGetProviderExtraConfig(t.clusterSpecTarget) { + providerGoogle[k] = v + } providersByName["google"] = providerGoogle } else if t.Cloud.ProviderID() == kops.CloudProviderAWS { providerAWS := make(map[string]interface{}) providerAWS["region"] = t.Region + for k, v := range tfGetProviderExtraConfig(t.clusterSpecTarget) { + providerAWS[k] = v + } providersByName["aws"] = providerAWS } else if t.Cloud.ProviderID() == kops.CloudProviderVSphere { providerVSphere := make(map[string]interface{}) providerVSphere["region"] = t.Region + for k, v := range tfGetProviderExtraConfig(t.clusterSpecTarget) { + providerVSphere[k] = v + } providersByName["vsphere"] = providerVSphere }