Skip to content

Commit

Permalink
Merge pull request #2787 from dlipovetsky/user-defined-elb-name
Browse files Browse the repository at this point in the history
feat: Bring your own control plane ELB
  • Loading branch information
k8s-ci-robot authored Nov 2, 2021
2 parents d2c1932 + 138bcac commit 461ef72
Show file tree
Hide file tree
Showing 18 changed files with 669 additions and 152 deletions.
17 changes: 17 additions & 0 deletions api/v1alpha3/awscluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,22 @@ func (r *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
restoreInstance(restored.Status.Bastion, dst.Status.Bastion)
}

if restored.Spec.ControlPlaneLoadBalancer != nil {
if dst.Spec.ControlPlaneLoadBalancer == nil {
dst.Spec.ControlPlaneLoadBalancer = &infrav1.AWSLoadBalancerSpec{}
}
restoreControlPlaneLoadBalancer(restored.Spec.ControlPlaneLoadBalancer, dst.Spec.ControlPlaneLoadBalancer)
}

return nil
}

// restoreControlPlaneLoadBalancer manually restores the control plane loadbalancer data.
// Assumes restored and dst are non-nil.
func restoreControlPlaneLoadBalancer(restored, dst *infrav1.AWSLoadBalancerSpec) {
dst.Name = restored.Name
}

// ConvertFrom converts the v1beta1 AWSCluster receiver to a v1alpha3 AWSCluster.
func (r *AWSCluster) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*infrav1.AWSCluster)
Expand Down Expand Up @@ -107,3 +120,7 @@ func Convert_v1beta1_NetworkStatus_To_v1alpha3_Network(in *infrav1.NetworkStatus
}
return nil
}

func Convert_v1beta1_AWSLoadBalancerSpec_To_v1alpha3_AWSLoadBalancerSpec(in *infrav1.AWSLoadBalancerSpec, out *AWSLoadBalancerSpec, s apiconversion.Scope) error {
return autoConvert_v1beta1_AWSLoadBalancerSpec_To_v1alpha3_AWSLoadBalancerSpec(in, out, s)
}
36 changes: 24 additions & 12 deletions api/v1alpha3/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 37 additions & 2 deletions api/v1alpha4/awscluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,45 @@ import (
func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*infrav1.AWSCluster)

return Convert_v1alpha4_AWSCluster_To_v1beta1_AWSCluster(src, dst, nil)
if err := Convert_v1alpha4_AWSCluster_To_v1beta1_AWSCluster(src, dst, nil); err != nil {
return err
}
// Manually restore data.
restored := &infrav1.AWSCluster{}
if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok {
return err
}

if restored.Spec.ControlPlaneLoadBalancer != nil {
if dst.Spec.ControlPlaneLoadBalancer == nil {
dst.Spec.ControlPlaneLoadBalancer = &infrav1.AWSLoadBalancerSpec{}
}
restoreControlPlaneLoadBalancer(restored.Spec.ControlPlaneLoadBalancer, dst.Spec.ControlPlaneLoadBalancer)
}

return nil
}

// restoreControlPlaneLoadBalancer manually restores the control plane loadbalancer data.
// Assumes restored and dst are non-nil.
func restoreControlPlaneLoadBalancer(restored, dst *infrav1.AWSLoadBalancerSpec) {
dst.Name = restored.Name
}

// ConvertFrom converts the v1beta1 AWSCluster receiver to a v1alpha4 AWSCluster.
func (r *AWSCluster) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*infrav1.AWSCluster)

return Convert_v1beta1_AWSCluster_To_v1alpha4_AWSCluster(src, r, nil)
if err := Convert_v1beta1_AWSCluster_To_v1alpha4_AWSCluster(src, r, nil); err != nil {
return err
}

// Preserve Hub data on down-conversion.
if err := utilconversion.MarshalData(src, r); err != nil {
return err
}

return nil
}

// ConvertTo converts the v1alpha3 AWSCluster receiver to a v1beta1 AWSCluster.
Expand Down Expand Up @@ -101,3 +132,7 @@ func (r *AWSClusterList) ConvertFrom(srcRaw conversion.Hub) error {

return Convert_v1beta1_AWSClusterList_To_v1alpha4_AWSClusterList(src, r, nil)
}

func Convert_v1beta1_AWSLoadBalancerSpec_To_v1alpha4_AWSLoadBalancerSpec(in *infrav1.AWSLoadBalancerSpec, out *AWSLoadBalancerSpec, s apiconversion.Scope) error {
return autoConvert_v1beta1_AWSLoadBalancerSpec_To_v1alpha4_AWSLoadBalancerSpec(in, out, s)
}
3 changes: 2 additions & 1 deletion api/v1alpha4/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func SetDefaults_Labels(obj *metav1.ObjectMeta) { //nolint:golint,stylecheck
// Defaults to set label if no labels have been set
if obj.Labels == nil {
obj.Labels = map[string]string{
clusterv1alpha4.ClusterctlMoveHierarchyLabelName: ""}
clusterv1alpha4.ClusterctlMoveHierarchyLabelName: "",
}
}
}
36 changes: 24 additions & 12 deletions api/v1alpha4/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions api/v1beta1/awscluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ type Bastion struct {

// AWSLoadBalancerSpec defines the desired state of an AWS load balancer.
type AWSLoadBalancerSpec struct {
// Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique
// within your set of load balancers for the region, must have a maximum of 32 characters, must
// contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once
// set, the value cannot be changed.
// +kubebuilder:validation:MaxLength:=32
// +kubebuilder:validation:Pattern=`^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$`
// +optional
Name *string `json:"name,omitempty"`

// Scheme sets the scheme of the load balancer (defaults to internet-facing)
// +kubebuilder:default=internet-facing
// +kubebuilder:validation:Enum=internet-facing;internal
Expand Down
7 changes: 7 additions & 0 deletions api/v1beta1/awscluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ func (r *AWSCluster) ValidateUpdate(old runtime.Object) error {
)
}
}
// If old name was not nil, the new name should be the same.
if existingLoadBalancer.Name != nil && !reflect.DeepEqual(existingLoadBalancer.Name, newLoadBalancer.Name) {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "controlPlaneLoadBalancer", "name"),
r.Spec.ControlPlaneLoadBalancer.Name, "field is immutable"),
)
}
}

if !reflect.DeepEqual(oldC.Spec.ControlPlaneEndpoint, clusterv1.APIEndpoint{}) &&
Expand Down
37 changes: 37 additions & 0 deletions api/v1beta1/awscluster_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
. "github.com/onsi/gomega"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -137,6 +138,42 @@ func TestAWSCluster_ValidateUpdate(t *testing.T) {
},
wantErr: true,
},
{
name: "controlPlaneLoadBalancer name is immutable once set",
oldCluster: &AWSCluster{
Spec: AWSClusterSpec{
ControlPlaneLoadBalancer: &AWSLoadBalancerSpec{
Name: aws.String("old-apiserver"),
},
},
},
newCluster: &AWSCluster{
Spec: AWSClusterSpec{
ControlPlaneLoadBalancer: &AWSLoadBalancerSpec{
Name: aws.String("new-apiserver"),
},
},
},
wantErr: true,
},
{
name: "controlPlaneLoadBalancer name can be set if undefined",
oldCluster: &AWSCluster{
Spec: AWSClusterSpec{
ControlPlaneLoadBalancer: &AWSLoadBalancerSpec{
Name: nil,
},
},
},
newCluster: &AWSCluster{
Spec: AWSClusterSpec{
ControlPlaneLoadBalancer: &AWSLoadBalancerSpec{
Name: aws.String("example-apiserver"),
},
},
},
wantErr: false,
},
{
name: "controlPlaneLoadBalancer scheme is immutable",
oldCluster: &AWSCluster{
Expand Down
10 changes: 10 additions & 0 deletions api/v1beta1/network_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ type ClassicELB struct {
Tags map[string]string `json:"tags,omitempty"`
}

// IsUnmanaged returns true if the Classic ELB is unmanaged.
func (b *ClassicELB) IsUnmanaged(clusterName string) bool {
return b.Name != "" && !Tags(b.Tags).HasOwned(clusterName)
}

// IsManaged returns true if Classic ELB is managed.
func (b *ClassicELB) IsManaged(clusterName string) bool {
return !b.IsUnmanaged(clusterName)
}

// ClassicELBAttributes defines extra attributes associated with a classic load balancer.
type ClassicELBAttributes struct {
// IdleTimeout is time that the connection is allowed to be idle (no data
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,15 @@ spec:
registered instances in its Availability Zone only. \n Defaults
to false."
type: boolean
name:
description: Name sets the name of the classic ELB load balancer.
As per AWS, the name must be unique within your set of load
balancers for the region, must have a maximum of 32 characters,
must contain only alphanumeric characters or hyphens, and cannot
begin or end with a hyphen. Once set, the value cannot be changed.
maxLength: 32
pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$
type: string
scheme:
default: internet-facing
description: Scheme sets the scheme of the load balancer (defaults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,16 @@ spec:
registered instances in its Availability Zone only.
\n Defaults to false."
type: boolean
name:
description: Name sets the name of the classic ELB load
balancer. As per AWS, the name must be unique within
your set of load balancers for the region, must have
a maximum of 32 characters, must contain only alphanumeric
characters or hyphens, and cannot begin or end with
a hyphen. Once set, the value cannot be changed.
maxLength: 32
pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$
type: string
scheme:
default: internet-facing
description: Scheme sets the scheme of the load balancer
Expand Down
Loading

0 comments on commit 461ef72

Please sign in to comment.