Skip to content

Commit 0820db4

Browse files
committed
zones: initial implementation of Zones interface
1 parent e3fcc43 commit 0820db4

File tree

3 files changed

+99
-127
lines changed

3 files changed

+99
-127
lines changed

pkg/providers/v2/instances.go

+59-91
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ import (
2222
"net"
2323
"strings"
2424

25+
"k8s.io/klog/v2"
26+
2527
"github.com/aws/aws-sdk-go/aws"
2628
"github.com/aws/aws-sdk-go/aws/credentials"
2729
"github.com/aws/aws-sdk-go/aws/session"
2830
"github.com/aws/aws-sdk-go/service/ec2"
2931

3032
v1 "k8s.io/api/core/v1"
33+
"k8s.io/apimachinery/pkg/types"
3134
cloudprovider "k8s.io/cloud-provider"
3235
)
3336

@@ -71,20 +74,10 @@ type instances struct {
7174

7275
// InstanceExists indicates whether a given node exists according to the cloud provider
7376
func (i *instances) InstanceExists(ctx context.Context, node *v1.Node) (bool, error) {
74-
var err error
75-
if node.Spec.ProviderID == "" {
76-
_, err = getInstanceByPrivateDNSName(ctx, node.Name, i.ec2)
77-
if err == cloudprovider.InstanceNotFound {
78-
return false, nil
79-
}
80-
81-
if err != nil {
82-
return false, err
83-
}
84-
}
77+
_, err := i.getInstance(ctx, node)
8578

86-
_, err = getInstanceByProviderID(ctx, node.Spec.ProviderID, i.ec2)
8779
if err == cloudprovider.InstanceNotFound {
80+
klog.V(6).Infof("instance not found for node: %s", node.Name)
8881
return false, nil
8982
}
9083

@@ -97,28 +90,31 @@ func (i *instances) InstanceExists(ctx context.Context, node *v1.Node) (bool, er
9790

9891
// InstanceShutdown returns true if the instance is shutdown according to the cloud provider.
9992
func (i *instances) InstanceShutdown(ctx context.Context, node *v1.Node) (bool, error) {
100-
if node.Spec.ProviderID == "" {
101-
return i.instanceShutdownByPrivateDNSName(ctx, node.Name)
93+
ec2Instance, err := i.getInstance(ctx, node)
94+
if err != nil {
95+
return false, err
96+
}
97+
98+
if ec2Instance.State != nil {
99+
state := aws.StringValue(ec2Instance.State.Name)
100+
// valid state for detaching volumes
101+
if state == ec2.InstanceStateNameStopped {
102+
return true, nil
103+
}
102104
}
103105

104-
return i.instanceShutdownByProviderID(ctx, node.Spec.ProviderID)
106+
return false, nil
105107
}
106108

107109
// InstanceMetadata returns the instance's metadata.
108110
func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) {
109111
var err error
110112
var ec2Instance *ec2.Instance
111-
if node.Spec.ProviderID == "" {
112-
// TODO: support node name policy other than private DNS names
113-
ec2Instance, err = getInstanceByPrivateDNSName(ctx, node.Name, i.ec2)
114-
if err != nil {
115-
return nil, err
116-
}
117-
} else {
118-
ec2Instance, err = getInstanceByProviderID(ctx, node.Spec.ProviderID, i.ec2)
119-
if err != nil {
120-
return nil, err
121-
}
113+
114+
// TODO: support node name policy other than private DNS names
115+
ec2Instance, err = i.getInstance(ctx, node)
116+
if err != nil {
117+
return nil, err
122118
}
123119

124120
nodeAddresses, err := nodeAddressesForInstance(ec2Instance)
@@ -140,20 +136,29 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
140136
return metadata, nil
141137
}
142138

143-
// getInstanceByProviderID returns the instance if the instance with the given provider id still exists.
139+
// getInstance returns the instance if the instance with the given node info still exists.
144140
// If false an error will be returned, the instance will be immediately deleted by the cloud controller manager.
145-
func getInstanceByProviderID(ctx context.Context, providerID string, ec2Client EC2) (*ec2.Instance, error) {
146-
instanceID, err := parseInstanceIDFromProviderID(providerID)
147-
if err != nil {
148-
return nil, err
141+
func (i *instances) getInstance(ctx context.Context, node *v1.Node) (*ec2.Instance, error) {
142+
if node.Spec.ProviderID == "" {
143+
// get Instance by node name
144+
klog.V(4).Infof("looking for node by private DNS name %v", node.Name)
145+
return getInstanceByPrivateDNSName(ctx, types.NodeName(node.Name), i.ec2)
149146
}
150147

148+
// get Instance by provider ID
149+
klog.V(4).Infof("looking for node by provider ID %v", node.Spec.ProviderID)
150+
return getInstanceByProviderID(ctx, node.Spec.ProviderID, i.ec2)
151+
}
152+
153+
// getInstanceByPrivateDNSName returns the instance if the instance with the given nodeName exists.
154+
// If false an error will be returned, the instance will be immediately deleted by the cloud controller manager.
155+
func getInstanceByPrivateDNSName(ctx context.Context, nodeName types.NodeName, ec2Client EC2) (*ec2.Instance, error) {
151156
request := &ec2.DescribeInstancesInput{
152-
InstanceIds: []*string{aws.String(instanceID)},
153157
Filters: []*ec2.Filter{
154-
newEc2Filter("instance-state-name", aliveFilter...),
158+
newEc2Filter("private-dns-name", string(nodeName)),
155159
},
156160
}
161+
klog.V(4).Infof("looking for node by private DNS name %v", nodeName)
157162

158163
instances := []*ec2.Instance{}
159164
var nextToken *string
@@ -179,21 +184,29 @@ func getInstanceByProviderID(ctx context.Context, providerID string, ec2Client E
179184
}
180185

181186
if len(instances) > 1 {
182-
return nil, fmt.Errorf("multiple instances found with provider ID: %s", instanceID)
187+
return nil, fmt.Errorf("getInstance: multiple instances found")
188+
}
189+
190+
state := instances[0].State.Name
191+
if *state == ec2.InstanceStateNameTerminated {
192+
return nil, fmt.Errorf("instance %v is terminated", instances[0].InstanceId)
183193
}
184194

185195
return instances[0], nil
186196
}
187197

188-
// getInstanceByPrivateDNSName returns the instance if the instance with the given provider id still exists.
198+
// getInstanceByProviderID returns the instance if the instance with the given providerID exists.
189199
// If false an error will be returned, the instance will be immediately deleted by the cloud controller manager.
190-
func getInstanceByPrivateDNSName(ctx context.Context, nodeName string, ec2Client EC2) (*ec2.Instance, error) {
200+
func getInstanceByProviderID(ctx context.Context, providerID string, ec2Client EC2) (*ec2.Instance, error) {
201+
instanceID, err := parseInstanceIDFromProviderID(providerID)
202+
if err != nil {
203+
return nil, err
204+
}
205+
191206
request := &ec2.DescribeInstancesInput{
192-
Filters: []*ec2.Filter{
193-
newEc2Filter("private-dns-name", nodeName),
194-
newEc2Filter("instance-state-name", aliveFilter...),
195-
},
207+
InstanceIds: []*string{aws.String(instanceID)},
196208
}
209+
klog.V(4).Infof("looking for node by provider ID %v", providerID)
197210

198211
instances := []*ec2.Instance{}
199212
var nextToken *string
@@ -219,55 +232,18 @@ func getInstanceByPrivateDNSName(ctx context.Context, nodeName string, ec2Client
219232
}
220233

221234
if len(instances) > 1 {
222-
return nil, fmt.Errorf("multiple instances found with private DNS name: %s", nodeName)
223-
}
224-
225-
return instances[0], nil
226-
}
227-
228-
// instanceShutdownByProviderID returns true if the instance is shutdown according to the cloud provider.
229-
func (i *instances) instanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) {
230-
ec2Instance, err := getInstanceByProviderID(ctx, providerID, i.ec2)
231-
if err != nil {
232-
if err == cloudprovider.InstanceNotFound {
233-
// We don't have live ec2Instance
234-
return true, nil
235-
}
236-
return false, err
235+
return nil, fmt.Errorf("getInstance: multiple instances found")
237236
}
238237

239-
if ec2Instance.State != nil {
240-
state := aws.StringValue(ec2Instance.State.Name)
241-
if state == ec2.InstanceStateNameStopping || state == ec2.InstanceStateNameStopped {
242-
return true, nil
243-
}
238+
state := instances[0].State.Name
239+
if *state == ec2.InstanceStateNameTerminated {
240+
return nil, fmt.Errorf("instance %v is terminated", instances[0].InstanceId)
244241
}
245242

246-
return false, nil
247-
}
248-
249-
// instanceShutdownByPrivateDNSName returns true if the instance is shutdown according to the cloud provider.
250-
func (i *instances) instanceShutdownByPrivateDNSName(ctx context.Context, nodeName string) (bool, error) {
251-
ec2Instance, err := getInstanceByPrivateDNSName(ctx, nodeName, i.ec2)
252-
if err != nil {
253-
if err == cloudprovider.InstanceNotFound {
254-
// We don't have live ec2Instance
255-
return true, nil
256-
}
257-
return false, err
258-
}
259-
260-
if ec2Instance.State != nil {
261-
state := aws.StringValue(ec2Instance.State.Name)
262-
if state == ec2.InstanceStateNameStopping || state == ec2.InstanceStateNameStopped {
263-
return true, nil
264-
}
265-
}
266-
267-
return false, nil
243+
return instances[0], nil
268244
}
269245

270-
// nodeAddressesForInstance returns a list of v1.NodeAddress for the give instance.
246+
// nodeAddresses for Instance returns a list of v1.NodeAddress for the give instance.
271247
// TODO: should we support ExternalIP by default?
272248
func nodeAddressesForInstance(instance *ec2.Instance) ([]v1.NodeAddress, error) {
273249
if instance == nil {
@@ -340,14 +316,6 @@ func parseInstanceIDFromProviderID(providerID string) (string, error) {
340316
return instanceID, nil
341317
}
342318

343-
var aliveFilter = []string{
344-
ec2.InstanceStateNamePending,
345-
ec2.InstanceStateNameRunning,
346-
ec2.InstanceStateNameShuttingDown,
347-
ec2.InstanceStateNameStopping,
348-
ec2.InstanceStateNameStopped,
349-
}
350-
351319
func newEc2Filter(name string, values ...string) *ec2.Filter {
352320
filter := &ec2.Filter{
353321
Name: aws.String(name),

0 commit comments

Comments
 (0)