Skip to content

Commit 978003e

Browse files
committed
Look up instance by providerID and node name consistently.
Currently, some instance operations look up instances by providerID and then fall back to node name, and other operations just use providerID. This causes problems using the cluster api, since nodes aren't provisioned with a providerID initially. This patch looks up instances by both providerID and node name consistently, and lightly refactors lookups to avoid repeat queries.
1 parent 53e7b3a commit 978003e

1 file changed

Lines changed: 33 additions & 44 deletions

File tree

internal/provider/instances_v2.go

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ package provider
66

77
import (
88
"context"
9+
"errors"
910
"fmt"
10-
"strings"
1111
"time"
1212

1313
"github.com/oxidecomputer/oxide.go/oxide"
@@ -21,6 +21,8 @@ var _ cloudprovider.InstancesV2 = (*InstancesV2)(nil)
2121
// gibibyte is the number of bytes in a gibibyte.
2222
const gibibyte = 1024 * 1024 * 1024
2323

24+
var errNotFound = errors.New("instance not found")
25+
2426
// InstancesV2 implements [cloudprovider.InstancesV2] to provide Oxide specific
2527
// instance functionality.
2628
type InstancesV2 struct {
@@ -36,19 +38,12 @@ func (i *InstancesV2) InstanceExists(ctx context.Context, node *v1.Node) (bool,
3638
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
3739
defer cancel()
3840

39-
instanceID, err := InstanceIDFromProviderID(node.Spec.ProviderID)
41+
_, err := i.getInstance(ctx, node)
4042
if err != nil {
41-
return false, fmt.Errorf("failed retrieving instance id from provider id: %w", err)
42-
}
43-
44-
if _, err := i.client.InstanceView(ctx, oxide.InstanceViewParams{
45-
Instance: oxide.NameOrId(instanceID),
46-
}); err != nil {
47-
if strings.Contains(err.Error(), "NotFound") {
43+
if errors.Is(err, errNotFound) {
4844
return false, nil
4945
}
50-
51-
return false, fmt.Errorf("failed viewing oxide instance %s: %v", instanceID, err)
46+
return false, fmt.Errorf("failed retrieving instance: %w", err)
5247
}
5348

5449
return true, nil
@@ -63,32 +58,23 @@ func (i *InstancesV2) InstanceMetadata(
6358
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
6459
defer cancel()
6560

66-
// Get the instance ID, either from the provider ID or by looking up by name.
67-
instanceID, err := i.getInstanceID(ctx, node)
61+
instance, err := i.getInstance(ctx, node)
6862
if err != nil {
69-
return nil, err
70-
}
71-
72-
// Retrieve the instance details.
73-
instance, err := i.client.InstanceView(ctx, oxide.InstanceViewParams{
74-
Instance: oxide.NameOrId(instanceID),
75-
})
76-
if err != nil {
77-
return nil, fmt.Errorf("failed viewing oxide instance: %v", err)
63+
return nil, fmt.Errorf("failed retrieving instance: %w", err)
7864
}
7965

8066
nics, err := i.client.InstanceNetworkInterfaceList(
8167
ctx,
8268
oxide.InstanceNetworkInterfaceListParams{
83-
Instance: oxide.NameOrId(instanceID),
69+
Instance: oxide.NameOrId(instance.Id),
8470
},
8571
)
8672
if err != nil {
8773
return nil, fmt.Errorf("failed listing instance network interfaces: %v", err)
8874
}
8975

9076
externalIPs, err := i.client.InstanceExternalIpList(ctx, oxide.InstanceExternalIpListParams{
91-
Instance: oxide.NameOrId(instanceID),
77+
Instance: oxide.NameOrId(instance.Id),
9278
})
9379
if err != nil {
9480
return nil, fmt.Errorf("failed listing instance external ips: %v", err)
@@ -148,46 +134,49 @@ func (i *InstancesV2) InstanceMetadata(
148134
}
149135

150136
return &cloudprovider.InstanceMetadata{
151-
ProviderID: NewProviderID(instanceID),
137+
ProviderID: NewProviderID(instance.Id),
152138
InstanceType: fmt.Sprintf("%d-%d", instance.Ncpus, instance.Memory/gibibyte),
153139
NodeAddresses: nodeAddresses,
154140
}, nil
155141
}
156142

157-
// getInstanceID retrieves the instance ID either from the node's provider ID
143+
// getInstance retrieves the instance, either from the node's provider ID
158144
// or by looking up the instance by name.
159-
func (i *InstancesV2) getInstanceID(ctx context.Context, node *v1.Node) (string, error) {
145+
func (i *InstancesV2) getInstance(ctx context.Context, node *v1.Node) (*oxide.Instance, error) {
146+
var params oxide.InstanceViewParams
147+
160148
if node.Spec.ProviderID != "" {
161-
return InstanceIDFromProviderID(node.Spec.ProviderID)
149+
instanceID, err := InstanceIDFromProviderID(node.Spec.ProviderID)
150+
if err != nil {
151+
return nil, fmt.Errorf("failed parsing provider id: %w", err)
152+
}
153+
params.Instance = oxide.NameOrId(instanceID)
154+
} else {
155+
params.Project = oxide.NameOrId(i.project)
156+
params.Instance = oxide.NameOrId(node.GetName())
162157
}
163158

164-
// If no provider ID is set, look up the instance by name.
165-
instance, err := i.client.InstanceView(ctx, oxide.InstanceViewParams{
166-
Project: oxide.NameOrId(i.project),
167-
Instance: oxide.NameOrId(node.GetName()),
168-
})
159+
instance, err := i.client.InstanceView(ctx, params)
169160
if err != nil {
170-
return "", fmt.Errorf("failed viewing oxide instance by name: %v", err)
161+
var httpErr *oxide.HTTPError
162+
if errors.As(err, &httpErr) && httpErr.ErrorResponse.ErrorCode == "ObjectNotFound" {
163+
return nil, errNotFound
164+
}
165+
166+
return nil, fmt.Errorf("failed looking up oxide instance: %w", err)
171167
}
172168

173-
return instance.Id, nil
169+
return instance, nil
174170
}
175171

176172
// InstanceShutdown checks whether the provided node is shut down in Oxide.
177173
func (i *InstancesV2) InstanceShutdown(ctx context.Context, node *v1.Node) (bool, error) {
178174
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
179175
defer cancel()
180176

181-
instanceID, err := InstanceIDFromProviderID(node.Spec.ProviderID)
182-
if err != nil {
183-
return false, fmt.Errorf("failed retrieving instance id from provider id: %w", err)
184-
}
185-
186-
instance, err := i.client.InstanceView(ctx, oxide.InstanceViewParams{
187-
Instance: oxide.NameOrId(instanceID),
188-
})
177+
instance, err := i.getInstance(ctx, node)
189178
if err != nil {
190-
return false, fmt.Errorf("failed viewing oxide instance %s: %v", instanceID, err)
179+
return false, fmt.Errorf("failed retrieving instance: %w", err)
191180
}
192181

193182
return instance.RunState == oxide.InstanceStateStopped, nil

0 commit comments

Comments
 (0)