diff --git a/api/v1alpha2/zz_generated.conversion.go b/api/v1alpha2/zz_generated.conversion.go index 72f53e0906..644eb29a24 100644 --- a/api/v1alpha2/zz_generated.conversion.go +++ b/api/v1alpha2/zz_generated.conversion.go @@ -1009,6 +1009,7 @@ func autoConvert_v1alpha3_Instance_To_v1alpha2_Instance(in *v1alpha3.Instance, o // WARNING: in.RootVolume requires manual conversion: does not exist in peer-type out.NetworkInterfaces = *(*[]string)(unsafe.Pointer(&in.NetworkInterfaces)) out.Tags = *(*map[string]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type return nil } diff --git a/api/v1alpha3/types.go b/api/v1alpha3/types.go index 386cfcfbce..b71d269495 100644 --- a/api/v1alpha3/types.go +++ b/api/v1alpha3/types.go @@ -554,6 +554,9 @@ type Instance struct { // The tags associated with the instance. Tags map[string]string `json:"tags,omitempty"` + + // Availability zone of instance + AvailabilityZone string `json:"availabilityZone,omitempty"` } // RootVolume encapsulates the configuration options for the root volume diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml index 0b9571a180..72652d4de1 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml @@ -638,6 +638,9 @@ spec: - type type: object type: array + availabilityZone: + description: Availability zone of instance + type: string ebsOptimized: description: Indicates whether the instance is optimized for Amazon EBS I/O. diff --git a/controllers/awsmachine_controller.go b/controllers/awsmachine_controller.go index cf683ee592..56a19a982d 100644 --- a/controllers/awsmachine_controller.go +++ b/controllers/awsmachine_controller.go @@ -18,7 +18,6 @@ package controllers import ( "context" - "fmt" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -411,7 +410,7 @@ func (r *AWSMachineReconciler) reconcileNormal(_ context.Context, machineScope * } // Make sure Spec.ProviderID is always set. - machineScope.SetProviderID(fmt.Sprintf("aws:////%s", instance.ID)) + machineScope.SetProviderID(instance.ID, instance.AvailabilityZone) // See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html diff --git a/pkg/cloud/scope/machine.go b/pkg/cloud/scope/machine.go index 78f635ec10..d6363508f6 100644 --- a/pkg/cloud/scope/machine.go +++ b/pkg/cloud/scope/machine.go @@ -19,6 +19,7 @@ package scope import ( "context" "encoding/base64" + "fmt" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -138,8 +139,9 @@ func (m *MachineScope) GetProviderID() string { } // SetProviderID sets the AWSMachine providerID in spec. -func (m *MachineScope) SetProviderID(v string) { - m.AWSMachine.Spec.ProviderID = pointer.StringPtr(v) +func (m *MachineScope) SetProviderID(instanceID, availabilityZone string) { + providerID := fmt.Sprintf("aws:///%s/%s", availabilityZone, instanceID) + m.AWSMachine.Spec.ProviderID = pointer.StringPtr(providerID) } // GetInstanceID returns the AWSMachine instance state from the status. diff --git a/pkg/cloud/scope/machine_test.go b/pkg/cloud/scope/machine_test.go index 18522d1e3a..740c9888d0 100644 --- a/pkg/cloud/scope/machine_test.go +++ b/pkg/cloud/scope/machine_test.go @@ -201,3 +201,24 @@ func TestSetSecretARN(t *testing.T) { t.Fatalf("prefix does not equal %s: %s", prefix, val) } } + +func TestSetProviderID(t *testing.T) { + scope, err := setupMachineScope() + if err != nil { + t.Fatal(err) + } + + scope.SetProviderID("test-id", "test-zone-1a") + providerID := *scope.AWSMachine.Spec.ProviderID + expectedProviderID := "aws:///test-zone-1a/test-id" + if providerID != expectedProviderID { + t.Fatalf("Expected providerID %s, got %s", expectedProviderID, providerID) + } + + scope.SetProviderID("test-id", "") + providerID = *scope.AWSMachine.Spec.ProviderID + expectedProviderID = "aws:////test-id" + if providerID != expectedProviderID { + t.Fatalf("Expected providerID %s, got %s", expectedProviderID, providerID) + } +} diff --git a/pkg/cloud/services/ec2/instances.go b/pkg/cloud/services/ec2/instances.go index 171902eb9e..8a2bff1bfb 100644 --- a/pkg/cloud/services/ec2/instances.go +++ b/pkg/cloud/services/ec2/instances.go @@ -624,6 +624,8 @@ func (s *Service) SDKToInstance(v *ec2.Instance) (*infrav1.Instance, error) { i.Addresses = s.getInstanceAddresses(v) + i.AvailabilityZone = aws.StringValue(v.Placement.AvailabilityZone) + return i, nil } diff --git a/pkg/cloud/services/ec2/instances_test.go b/pkg/cloud/services/ec2/instances_test.go index 51c39062e4..73c623bc0d 100644 --- a/pkg/cloud/services/ec2/instances_test.go +++ b/pkg/cloud/services/ec2/instances_test.go @@ -88,6 +88,7 @@ func TestInstanceIfExists(t *testing.T) { name: "instance exists", instanceID: "id-1", expect: func(m *mock_ec2iface.MockEC2APIMockRecorder) { + az := "test-zone-1a" m.DescribeInstances(gomock.Eq(&ec2.DescribeInstancesInput{ InstanceIds: []*string{aws.String("id-1")}, })). @@ -116,6 +117,9 @@ func TestInstanceIfExists(t *testing.T) { }, }, }, + Placement: &ec2.Placement{ + AvailabilityZone: &az, + }, }, }, }, @@ -269,6 +273,8 @@ func TestCreateInstance(t *testing.T) { }, } + az := "test-zone-1a" + testcases := []struct { name string machine clusterv1.Machine @@ -362,6 +368,9 @@ func TestCreateInstance(t *testing.T) { }, }, }, + Placement: &ec2.Placement{ + AvailabilityZone: &az, + }, }, }, }, nil) @@ -475,6 +484,9 @@ func TestCreateInstance(t *testing.T) { }, }, }, + Placement: &ec2.Placement{ + AvailabilityZone: &az, + }, }, }, }, nil) @@ -606,6 +618,9 @@ func TestCreateInstance(t *testing.T) { }, }, }, + Placement: &ec2.Placement{ + AvailabilityZone: &az, + }, }, }, }, nil) @@ -733,6 +748,9 @@ func TestCreateInstance(t *testing.T) { }, }, }, + Placement: &ec2.Placement{ + AvailabilityZone: &az, + }, }, }, }, nil) @@ -861,6 +879,9 @@ func TestCreateInstance(t *testing.T) { }, }, }, + Placement: &ec2.Placement{ + AvailabilityZone: &az, + }, }, }, }, nil)