-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adds gcp metadata provider support to cloudmeta package (#4155)
* feat: adds gcp metadata provider support to cloudmeta package This adds gcp metadata provider support to cloudmeta package. Fixes: #4128
- Loading branch information
1 parent
4e52b04
commit 0372277
Showing
3 changed files
with
142 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (C) 2024 ScyllaDB | ||
|
||
package cloudmeta | ||
|
||
import ( | ||
"context" | ||
"strings" | ||
|
||
"cloud.google.com/go/compute/metadata" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// gcpMetadata is a wrapper around gcp metadata client. | ||
type gcpMetadata struct { | ||
meta *metadata.Client | ||
} | ||
|
||
// newGCPMetadata returns gcp metadata provider. | ||
func newGCPMetadata() *gcpMetadata { | ||
return &gcpMetadata{ | ||
meta: metadata.NewClient(nil), | ||
} | ||
} | ||
|
||
// Metadata returns InstanceMetadata from gcp if available. | ||
func (gcp *gcpMetadata) Metadata(ctx context.Context) (InstanceMetadata, error) { | ||
machineType, err := gcp.getMachineType(ctx) | ||
if err != nil { | ||
return InstanceMetadata{}, errors.Wrap(err, "gcp.meta.GetWithContext") | ||
} | ||
return InstanceMetadata{ | ||
CloudProvider: CloudProviderGCP, | ||
InstanceType: machineType, | ||
}, nil | ||
} | ||
|
||
func (gcp *gcpMetadata) getMachineType(ctx context.Context) (string, error) { | ||
machineTypeResp, err := gcp.meta.GetWithContext(ctx, "instance/machine-type") | ||
if err != nil { | ||
return "", errors.Wrap(err, "gcp.meta.GetWithContext") | ||
} | ||
|
||
machineType, err := parseMachineTypeResponse(machineTypeResp) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return machineType, nil | ||
} | ||
|
||
// The machine type for this VM. This value has the following format: projects/PROJECT_NUM/machineTypes/MACHINE_TYPE. | ||
// See https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys#instance-metadata. | ||
func parseMachineTypeResponse(resp string) (string, error) { | ||
errUnexpectedFormat := errors.Errorf("unexpected machineType response format: %s", resp) | ||
|
||
parts := strings.Split(resp, "/") | ||
if len(parts) != 4 { | ||
return "", errUnexpectedFormat | ||
} | ||
|
||
if parts[2] != "machineTypes" { | ||
return "", errUnexpectedFormat | ||
} | ||
|
||
return parts[3], nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright (C) 2024 ScyllaDB | ||
|
||
package cloudmeta | ||
|
||
import "testing" | ||
|
||
func TestParseMachineTypeResponse(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
machineTypeResponse string | ||
|
||
expectedErr bool | ||
expected string | ||
}{ | ||
{ | ||
name: "everything is fine", | ||
machineTypeResponse: "projects/project1/machineTypes/machineType1", | ||
|
||
expectedErr: false, | ||
expected: "machineType1", | ||
}, | ||
{ | ||
name: "new response part is added", | ||
machineTypeResponse: "projects/project1/zone/zone1/machineTypes/machineType1", | ||
|
||
expectedErr: true, | ||
expected: "", | ||
}, | ||
{ | ||
name: "new response part is added after machineTypes part", | ||
machineTypeResponse: "projects/project1/machineTypes/machineType1/zones/zone1", | ||
|
||
expectedErr: true, | ||
expected: "", | ||
}, | ||
{ | ||
name: "parts are mixed up", | ||
machineTypeResponse: "machineTypes/machineType1/projects/project1", | ||
|
||
expectedErr: true, | ||
expected: "", | ||
}, | ||
{ | ||
name: "empty response", | ||
machineTypeResponse: "", | ||
|
||
expectedErr: true, | ||
expected: "", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
machineType, err := parseMachineTypeResponse(tc.machineTypeResponse) | ||
if tc.expectedErr && err == nil { | ||
t.Fatalf("expected err, but got %v", err) | ||
} | ||
if !tc.expectedErr && err != nil { | ||
t.Fatalf("unexpected err: %v", err) | ||
} | ||
|
||
if tc.expected != machineType { | ||
t.Fatalf("machineType(%s) != expected(%s)", machineType, tc.expected) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters