Skip to content

Commit 6a16bc2

Browse files
authored
fix: use timeouts, clean up return paths (#147)
Updated the code to: * Use timeouts * Remove unreachable returns * Refactor retreiving the instance ID * Validate `OXIDE_PROJECT`
1 parent c455c55 commit 6a16bc2

File tree

2 files changed

+47
-30
lines changed

2 files changed

+47
-30
lines changed

internal/provider/instances_v2.go

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"fmt"
99
"strings"
10+
"time"
1011

1112
"github.com/oxidecomputer/oxide.go/oxide"
1213
v1 "k8s.io/api/core/v1"
@@ -16,6 +17,9 @@ import (
1617

1718
var _ cloudprovider.InstancesV2 = (*InstancesV2)(nil)
1819

20+
// gibibyte is the number of bytes in a gibibyte.
21+
const gibibyte = 1024 * 1024 * 1024
22+
1923
// InstancesV2 implements [cloudprovider.InstancesV2] to provide Oxide specific
2024
// instance functionality.
2125
type InstancesV2 struct {
@@ -28,6 +32,9 @@ type InstancesV2 struct {
2832
// InstanceExists checks whether the provided Kubernetes node exists as instance
2933
// in Oxide.
3034
func (i *InstancesV2) InstanceExists(ctx context.Context, node *v1.Node) (bool, error) {
35+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
36+
defer cancel()
37+
3138
instanceID, err := InstanceIDFromProviderID(node.Spec.ProviderID)
3239
if err != nil {
3340
return false, fmt.Errorf("failed retrieving instance id from provider id: %w", err)
@@ -49,34 +56,21 @@ func (i *InstancesV2) InstanceExists(ctx context.Context, node *v1.Node) (bool,
4956
// InstanceMetadata populates the metadata for the provided node, notably
5057
// setting its provider ID.
5158
func (i *InstancesV2) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) {
52-
var (
53-
err error
54-
instance *oxide.Instance
55-
instanceID string
56-
)
59+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
60+
defer cancel()
5761

58-
if node.Spec.ProviderID != "" {
59-
instanceID, err = InstanceIDFromProviderID(node.Spec.ProviderID)
60-
if err != nil {
61-
return nil, fmt.Errorf("failed retrieving instance id from provider id: %w", err)
62-
}
63-
64-
instance, err = i.client.InstanceView(ctx, oxide.InstanceViewParams{
65-
Instance: oxide.NameOrId(instanceID),
66-
})
67-
if err != nil {
68-
return nil, fmt.Errorf("failed viewing oxide instance by id: %v", err)
69-
}
70-
} else {
71-
instance, err = i.client.InstanceView(ctx, oxide.InstanceViewParams{
72-
Project: oxide.NameOrId(i.project),
73-
Instance: oxide.NameOrId(node.GetName()),
74-
})
75-
if err != nil {
76-
return nil, fmt.Errorf("failed viewing oxide instance by name: %v", err)
77-
}
62+
// Get the instance ID, either from the provider ID or by looking up by name.
63+
instanceID, err := i.getInstanceID(ctx, node)
64+
if err != nil {
65+
return nil, err
66+
}
7867

79-
instanceID = instance.Id
68+
// Retrieve the instance details.
69+
instance, err := i.client.InstanceView(ctx, oxide.InstanceViewParams{
70+
Instance: oxide.NameOrId(instanceID),
71+
})
72+
if err != nil {
73+
return nil, fmt.Errorf("failed viewing oxide instance: %v", err)
8074
}
8175

8276
nics, err := i.client.InstanceNetworkInterfaceList(ctx, oxide.InstanceNetworkInterfaceListParams{
@@ -119,13 +113,35 @@ func (i *InstancesV2) InstanceMetadata(ctx context.Context, node *v1.Node) (*clo
119113

120114
return &cloudprovider.InstanceMetadata{
121115
ProviderID: NewProviderID(instanceID),
122-
InstanceType: fmt.Sprintf("%v-%v", instance.Ncpus, (instance.Memory / (1024 * 1024 * 1024))),
116+
InstanceType: fmt.Sprintf("%d-%d", instance.Ncpus, instance.Memory/gibibyte),
123117
NodeAddresses: nodeAddresses,
124118
}, nil
125119
}
126120

121+
// getInstanceID retrieves the instance ID either from the node's provider ID
122+
// or by looking up the instance by name.
123+
func (i *InstancesV2) getInstanceID(ctx context.Context, node *v1.Node) (string, error) {
124+
if node.Spec.ProviderID != "" {
125+
return InstanceIDFromProviderID(node.Spec.ProviderID)
126+
}
127+
128+
// If no provider ID is set, look up the instance by name.
129+
instance, err := i.client.InstanceView(ctx, oxide.InstanceViewParams{
130+
Project: oxide.NameOrId(i.project),
131+
Instance: oxide.NameOrId(node.GetName()),
132+
})
133+
if err != nil {
134+
return "", fmt.Errorf("failed viewing oxide instance by name: %v", err)
135+
}
136+
137+
return instance.Id, nil
138+
}
139+
127140
// InstanceShutdown checks whether the provided node is shut down in Oxide.
128141
func (i *InstancesV2) InstanceShutdown(ctx context.Context, node *v1.Node) (bool, error) {
142+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
143+
defer cancel()
144+
129145
instanceID, err := InstanceIDFromProviderID(node.Spec.ProviderID)
130146
if err != nil {
131147
return false, fmt.Errorf("failed retrieving instance id from provider id: %w", err)

internal/provider/provider.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,21 @@ func (o *Oxide) Initialize(clientBuilder cloudprovider.ControllerClientBuilder,
4848
kubernetesClient, err := clientBuilder.Client(Name)
4949
if err != nil {
5050
klog.Fatalf("failed to create kubernetes client: %v", err)
51-
return
5251
}
5352
o.k8sClient = kubernetesClient
5453

5554
oxideClient, err := oxide.NewClient(nil)
5655
if err != nil {
5756
klog.Fatalf("failed to create oxide client: %v", err)
58-
return
5957
}
6058
o.client = oxideClient
6159

6260
o.project = os.Getenv("OXIDE_PROJECT")
61+
if o.project == "" {
62+
klog.Fatalf("OXIDE_PROJECT environment variable is required")
63+
}
6364

64-
klog.InfoS("initialized cloud provider", "type", "oxide")
65+
klog.InfoS("initialized cloud provider", "type", "oxide", "project", o.project)
6566
}
6667

6768
// ProviderName returns the name of this cloud provider.

0 commit comments

Comments
 (0)