@@ -6,8 +6,8 @@ package provider
66
77import (
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.
2222const 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.
2628type 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.
177173func (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