mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-23 22:49:43 -05:00
[node operator] GCP: use canonical references
This commit is contained in:
parent
51cf638361
commit
80ebfab164
@ -8,6 +8,12 @@ import (
|
||||
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||
)
|
||||
|
||||
type projectAPI interface {
|
||||
Close() error
|
||||
Get(ctx context.Context, req *computepb.GetProjectRequest,
|
||||
opts ...gax.CallOption) (*computepb.Project, error)
|
||||
}
|
||||
|
||||
type instanceAPI interface {
|
||||
Close() error
|
||||
Get(ctx context.Context, req *computepb.GetInstanceRequest,
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
// Client is a client for the Google Compute Engine.
|
||||
type Client struct {
|
||||
projectID string
|
||||
projectAPI
|
||||
instanceAPI
|
||||
instanceTemplateAPI
|
||||
instanceGroupManagersAPI
|
||||
@ -29,8 +30,15 @@ func New(ctx context.Context, configPath string) (*Client, error) {
|
||||
}
|
||||
|
||||
var closers []closer
|
||||
projectAPI, err := compute.NewProjectsRESTClient(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
closers = append(closers, projectAPI)
|
||||
insAPI, err := compute.NewInstancesRESTClient(ctx)
|
||||
if err != nil {
|
||||
_ = closeAll(closers)
|
||||
return nil, err
|
||||
}
|
||||
closers = append(closers, insAPI)
|
||||
@ -53,6 +61,7 @@ func New(ctx context.Context, configPath string) (*Client, error) {
|
||||
}
|
||||
return &Client{
|
||||
projectID: projectID,
|
||||
projectAPI: projectAPI,
|
||||
instanceAPI: insAPI,
|
||||
instanceTemplateAPI: &instanceTemplateClient{templAPI},
|
||||
instanceGroupManagersAPI: &instanceGroupManagersClient{groupAPI},
|
||||
@ -64,6 +73,7 @@ func New(ctx context.Context, configPath string) (*Client, error) {
|
||||
// Close closes the client's connection.
|
||||
func (c *Client) Close() error {
|
||||
closers := []closer{
|
||||
c.projectAPI,
|
||||
c.instanceAPI,
|
||||
c.instanceTemplateAPI,
|
||||
c.instanceGroupManagersAPI,
|
||||
|
@ -10,6 +10,21 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type stubProjectAPI struct {
|
||||
project *computepb.Project
|
||||
getErr error
|
||||
}
|
||||
|
||||
func (a stubProjectAPI) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a stubProjectAPI) Get(ctx context.Context, req *computepb.GetProjectRequest,
|
||||
opts ...gax.CallOption,
|
||||
) (*computepb.Project, error) {
|
||||
return a.project, a.getErr
|
||||
}
|
||||
|
||||
type stubInstanceAPI struct {
|
||||
instance *computepb.Instance
|
||||
getErr error
|
||||
|
@ -1,6 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
@ -11,6 +12,18 @@ var (
|
||||
workerInstanceGroupNameRegex = regexp.MustCompile(`^(.*)worker(.*)$`)
|
||||
)
|
||||
|
||||
func (c *Client) canonicalInstanceGroupID(ctx context.Context, instanceGroupID string) (string, error) {
|
||||
project, zone, instanceGroup, err := splitInstanceGroupID(uriNormalize(instanceGroupID))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
project, err = c.canonicalProjectID(ctx, project)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("projects/%s/zones/%s/instanceGroupManagers/%s", project, zone, instanceGroup), nil
|
||||
}
|
||||
|
||||
// splitInstanceGroupID splits an instance group ID into core components.
|
||||
func splitInstanceGroupID(instanceGroupID string) (project, zone, instanceGroup string, err error) {
|
||||
matches := instanceGroupIDRegex.FindStringSubmatch(instanceGroupID)
|
||||
|
@ -14,6 +14,10 @@ func (c *Client) GetNodeImage(ctx context.Context, providerID string) (string, e
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
project, err = c.canonicalProjectID(ctx, project)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
instance, err := c.instanceAPI.Get(ctx, &computepb.GetInstanceRequest{
|
||||
Instance: instanceName,
|
||||
Project: project,
|
||||
@ -61,6 +65,10 @@ func (c *Client) GetScalingGroupID(ctx context.Context, providerID string) (stri
|
||||
if scalingGroupID == "" {
|
||||
return "", fmt.Errorf("instance %q has no created-by metadata", instanceName)
|
||||
}
|
||||
scalingGroupID, err = c.canonicalInstanceGroupID(ctx, scalingGroupID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return scalingGroupID, nil
|
||||
}
|
||||
|
||||
@ -70,6 +78,10 @@ func (c *Client) CreateNode(ctx context.Context, scalingGroupID string) (nodeNam
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
project, err = c.canonicalProjectID(ctx, project)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
instanceGroupManager, err := c.instanceGroupManagersAPI.Get(ctx, &computepb.GetInstanceGroupManagerRequest{
|
||||
InstanceGroupManager: instanceGroupName,
|
||||
Project: project,
|
||||
|
@ -116,8 +116,8 @@ func TestGetScalingGroupID(t *testing.T) {
|
||||
}{
|
||||
"scaling group is found": {
|
||||
providerID: "gce://project/zone/instance-name",
|
||||
createdBy: "projects/project/zones/zone/instanceGroups/instance-group",
|
||||
wantScalingGroupID: "projects/project/zones/zone/instanceGroups/instance-group",
|
||||
createdBy: "projects/project/zones/zone/instanceGroupManagers/instance-group",
|
||||
wantScalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group",
|
||||
},
|
||||
"splitting providerID fails": {
|
||||
providerID: "invalid",
|
||||
|
@ -0,0 +1,26 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
|
||||
"google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||
)
|
||||
|
||||
var numericProjectIDRegex = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
// canonicalProjectID returns the project id for a given project id or project number.
|
||||
func (c *Client) canonicalProjectID(ctx context.Context, project string) (string, error) {
|
||||
if !numericProjectIDRegex.MatchString(project) {
|
||||
return project, nil
|
||||
}
|
||||
computeProject, err := c.projectAPI.Get(ctx, &compute.GetProjectRequest{Project: project})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if computeProject == nil || computeProject.Name == nil {
|
||||
return "", errors.New("invalid project")
|
||||
}
|
||||
return *computeProject.Name, nil
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestCanonicalProjectID(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
projectID string
|
||||
project *computepb.Project
|
||||
getProjectErr error
|
||||
wantProjectID string
|
||||
wantErr bool
|
||||
}{
|
||||
"already canonical": {
|
||||
projectID: "project-12345",
|
||||
wantProjectID: "project-12345",
|
||||
},
|
||||
"numeric project id": {
|
||||
projectID: "12345",
|
||||
wantProjectID: "project-12345",
|
||||
project: &computepb.Project{Name: proto.String("project-12345")},
|
||||
},
|
||||
"numeric project id with error": {
|
||||
projectID: "12345",
|
||||
wantProjectID: "project-12345",
|
||||
getProjectErr: errors.New("get error"),
|
||||
wantErr: true,
|
||||
},
|
||||
"numeric project id with nil project": {
|
||||
projectID: "12345",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
client := Client{
|
||||
projectAPI: &stubProjectAPI{
|
||||
project: tc.project,
|
||||
getErr: tc.getProjectErr,
|
||||
},
|
||||
}
|
||||
gotID, err := client.canonicalProjectID(context.Background(), tc.projectID)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantProjectID, gotID)
|
||||
})
|
||||
}
|
||||
}
|
@ -109,7 +109,10 @@ func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlan
|
||||
if instanceGroupManager == nil || instanceGroupManager.Name == nil || instanceGroupManager.SelfLink == nil {
|
||||
continue
|
||||
}
|
||||
groupID := uriNormalize(*instanceGroupManager.SelfLink)
|
||||
groupID, err := c.canonicalInstanceGroupID(ctx, *instanceGroupManager.SelfLink)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("normalizing instance group ID: %w", err)
|
||||
}
|
||||
|
||||
if isControlPlaneInstanceGroup(*instanceGroupManager.Name) {
|
||||
controlPlaneGroupIDs = append(controlPlaneGroupIDs, groupID)
|
||||
|
Loading…
Reference in New Issue
Block a user