add gcp loadbalancer

This commit is contained in:
Leonard Cohnen 2022-06-09 22:26:36 +02:00 committed by 3u13r
parent 1e11188dac
commit e13f4d84c3
21 changed files with 1043 additions and 10 deletions

View file

@ -41,6 +41,34 @@ type firewallsAPI interface {
opts ...gax.CallOption) (Operation, error)
}
type forwardingRulesAPI interface {
Close() error
Delete(ctx context.Context, req *computepb.DeleteForwardingRuleRequest,
opts ...gax.CallOption) (Operation, error)
Insert(ctx context.Context, req *computepb.InsertForwardingRuleRequest,
opts ...gax.CallOption) (Operation, error)
Get(ctx context.Context, req *computepb.GetForwardingRuleRequest,
opts ...gax.CallOption) (*computepb.ForwardingRule, error)
SetLabels(ctx context.Context, req *computepb.SetLabelsForwardingRuleRequest,
opts ...gax.CallOption) (Operation, error)
}
type backendServicesAPI interface {
Close() error
Delete(ctx context.Context, req *computepb.DeleteRegionBackendServiceRequest,
opts ...gax.CallOption) (Operation, error)
Insert(ctx context.Context, req *computepb.InsertRegionBackendServiceRequest,
opts ...gax.CallOption) (Operation, error)
}
type healthChecksAPI interface {
Close() error
Delete(ctx context.Context, req *computepb.DeleteRegionHealthCheckRequest,
opts ...gax.CallOption) (Operation, error)
Insert(ctx context.Context, req *computepb.InsertRegionHealthCheckRequest,
opts ...gax.CallOption) (Operation, error)
}
type networksAPI interface {
Close() error
Delete(ctx context.Context, req *computepb.DeleteNetworkRequest,

View file

@ -219,6 +219,143 @@ func (a stubSubnetworksAPI) Delete(ctx context.Context, req *computepb.DeleteSub
}, nil
}
type stubBackendServicesAPI struct {
insertErr error
deleteErr error
}
func (a stubBackendServicesAPI) Close() error {
return nil
}
func (a stubBackendServicesAPI) Insert(ctx context.Context, req *computepb.InsertRegionBackendServiceRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.insertErr != nil {
return nil, a.insertErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
func (a stubBackendServicesAPI) Delete(ctx context.Context, req *computepb.DeleteRegionBackendServiceRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.deleteErr != nil {
return nil, a.deleteErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
type stubForwardingRulesAPI struct {
insertErr error
deleteErr error
getErr error
setLabelErr error
forwardingRule *computepb.ForwardingRule
}
func (a stubForwardingRulesAPI) Close() error {
return nil
}
func (a stubForwardingRulesAPI) Insert(ctx context.Context, req *computepb.InsertForwardingRuleRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.insertErr != nil {
return nil, a.insertErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
func (a stubForwardingRulesAPI) Delete(ctx context.Context, req *computepb.DeleteForwardingRuleRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.deleteErr != nil {
return nil, a.deleteErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
func (a stubForwardingRulesAPI) Get(ctx context.Context, req *computepb.GetForwardingRuleRequest,
opts ...gax.CallOption,
) (*computepb.ForwardingRule, error) {
if a.getErr != nil {
return nil, a.getErr
}
return a.forwardingRule, nil
}
func (a stubForwardingRulesAPI) SetLabels(ctx context.Context, req *computepb.SetLabelsForwardingRuleRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.deleteErr != nil {
return nil, a.setLabelErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
type stubHealthChecksAPI struct {
insertErr error
deleteErr error
}
func (a stubHealthChecksAPI) Close() error {
return nil
}
func (a stubHealthChecksAPI) Insert(ctx context.Context, req *computepb.InsertRegionHealthCheckRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.insertErr != nil {
return nil, a.insertErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
func (a stubHealthChecksAPI) Delete(ctx context.Context, req *computepb.DeleteRegionHealthCheckRequest,
opts ...gax.CallOption,
) (Operation, error) {
if a.deleteErr != nil {
return nil, a.deleteErr
}
return &stubOperation{
&computepb.Operation{
Name: proto.String("name"),
Region: proto.String("region"),
},
}, nil
}
type stubInstanceTemplateAPI struct {
deleteErr error
insertErr error

View file

@ -25,6 +25,9 @@ type Client struct {
networksAPI
subnetworksAPI
firewallsAPI
forwardingRulesAPI
backendServicesAPI
healthChecksAPI
instanceTemplateAPI
instanceGroupManagersAPI
iamAPI
@ -47,6 +50,11 @@ type Client struct {
zone string
region string
serviceAccount string
// loadbalancer
healthCheck string
backendService string
forwardingRule string
}
// NewFromDefault creates an uninitialized client.
@ -92,7 +100,31 @@ func NewFromDefault(ctx context.Context) (*Client, error) {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, fwAPI)
closers = append(closers, subnetAPI)
forwardingRulesAPI, err := compute.NewForwardingRulesRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, forwardingRulesAPI)
backendServicesAPI, err := compute.NewRegionBackendServicesRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, backendServicesAPI)
targetPoolsAPI, err := compute.NewTargetPoolsRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, targetPoolsAPI)
healthChecksAPI, err := compute.NewRegionHealthChecksRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, healthChecksAPI)
templAPI, err := compute.NewInstanceTemplatesRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
@ -124,6 +156,9 @@ func NewFromDefault(ctx context.Context) (*Client, error) {
networksAPI: &networksClient{netAPI},
subnetworksAPI: &subnetworksClient{subnetAPI},
firewallsAPI: &firewallsClient{fwAPI},
forwardingRulesAPI: &forwardingRulesClient{forwardingRulesAPI},
backendServicesAPI: &backendServicesClient{backendServicesAPI},
healthChecksAPI: &healthChecksClient{healthChecksAPI},
instanceTemplateAPI: &instanceTemplateClient{templAPI},
instanceGroupManagersAPI: &instanceGroupManagersClient{groupAPI},
iamAPI: &iamClient{iamAPI},
@ -147,12 +182,19 @@ func NewInitialized(ctx context.Context, project, zone, region, name string) (*C
func (c *Client) Close() error {
closers := []closer{
c.instanceAPI,
c.operationRegionAPI,
c.operationZoneAPI,
c.operationGlobalAPI,
c.networksAPI,
c.subnetworksAPI,
c.firewallsAPI,
c.forwardingRulesAPI,
c.backendServicesAPI,
c.healthChecksAPI,
c.instanceTemplateAPI,
c.instanceGroupManagersAPI,
c.iamAPI,
c.projectsAPI,
}
return closeAll(closers)
}
@ -246,6 +288,21 @@ func (c *Client) GetState() (state.ConstellationState, error) {
}
stat.GCPCoordinatorInstanceTemplate = c.coordinatorTemplate
if c.healthCheck == "" {
return state.ConstellationState{}, errors.New("client has no health check")
}
stat.GCPHealthCheck = c.healthCheck
if c.backendService == "" {
return state.ConstellationState{}, errors.New("client has no backend service")
}
stat.GCPBackendService = c.backendService
if c.forwardingRule == "" {
return state.ConstellationState{}, errors.New("client has no forwarding rule")
}
stat.GCPForwardingRule = c.forwardingRule
// service account does not have to be set at all times
stat.GCPServiceAccount = c.serviceAccount
@ -327,6 +384,21 @@ func (c *Client) SetState(stat state.ConstellationState) error {
}
c.coordinatorTemplate = stat.GCPCoordinatorInstanceTemplate
if stat.GCPHealthCheck == "" {
return errors.New("state has no health check")
}
c.healthCheck = stat.GCPHealthCheck
if stat.GCPBackendService == "" {
return errors.New("state has no backend service")
}
c.backendService = stat.GCPBackendService
if stat.GCPForwardingRule == "" {
return errors.New("state has no forwarding rule")
}
c.forwardingRule = stat.GCPForwardingRule
// service account does not have to be set at all times
c.serviceAccount = stat.GCPServiceAccount

View file

@ -44,6 +44,9 @@ func TestSetGetState(t *testing.T) {
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPServiceAccount: "service-account",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
},
"missing nodes": {
@ -67,6 +70,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -91,6 +97,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -120,6 +129,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -149,6 +161,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -178,6 +193,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -207,6 +225,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -236,6 +257,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -264,6 +288,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -293,6 +320,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -322,6 +352,9 @@ func TestSetGetState(t *testing.T) {
GCPSubnetwork: "subnet-id",
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -350,6 +383,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -379,6 +415,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -408,6 +447,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -437,6 +479,9 @@ func TestSetGetState(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -466,6 +511,9 @@ func TestSetGetState(t *testing.T) {
GCPSubnetwork: "subnet-id",
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
@ -495,6 +543,105 @@ func TestSetGetState(t *testing.T) {
GCPSubnetwork: "subnet-id",
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
"missing backend service": {
state: state.ConstellationState{
CloudProvider: cloudprovider.GCP.String(),
GCPNodes: cloudtypes.Instances{
"id-1": {
PublicIP: "ip1",
PrivateIP: "ip2",
},
},
GCPCoordinators: cloudtypes.Instances{
"id-1": {
PublicIP: "ip3",
PrivateIP: "ip4",
},
},
GCPNodeInstanceGroup: "group-id",
GCPCoordinatorInstanceGroup: "group-id",
GCPProject: "proj-id",
GCPZone: "zone-id",
GCPRegion: "region-id",
Name: "name",
UID: "uid",
GCPNetwork: "net-id",
GCPSubnetwork: "subnet-id",
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
"missing health check": {
state: state.ConstellationState{
CloudProvider: cloudprovider.GCP.String(),
GCPNodes: cloudtypes.Instances{
"id-1": {
PublicIP: "ip1",
PrivateIP: "ip2",
},
},
GCPCoordinators: cloudtypes.Instances{
"id-1": {
PublicIP: "ip3",
PrivateIP: "ip4",
},
},
GCPNodeInstanceGroup: "group-id",
GCPCoordinatorInstanceGroup: "group-id",
GCPProject: "proj-id",
GCPZone: "zone-id",
GCPRegion: "region-id",
Name: "name",
UID: "uid",
GCPNetwork: "net-id",
GCPSubnetwork: "subnet-id",
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPForwardingRule: "forwarding-rule-id",
},
wantErr: true,
},
"missing forwarding rule": {
state: state.ConstellationState{
CloudProvider: cloudprovider.GCP.String(),
GCPNodes: cloudtypes.Instances{
"id-1": {
PublicIP: "ip1",
PrivateIP: "ip2",
},
},
GCPCoordinators: cloudtypes.Instances{
"id-1": {
PublicIP: "ip3",
PrivateIP: "ip4",
},
},
GCPNodeInstanceGroup: "group-id",
GCPCoordinatorInstanceGroup: "group-id",
GCPProject: "proj-id",
GCPZone: "zone-id",
GCPRegion: "region-id",
Name: "name",
UID: "uid",
GCPNetwork: "net-id",
GCPSubnetwork: "subnet-id",
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
},
wantErr: true,
},
@ -549,6 +696,9 @@ func TestSetGetState(t *testing.T) {
nodeTemplate: tc.state.GCPNodeInstanceTemplate,
coordinatorTemplate: tc.state.GCPCoordinatorInstanceTemplate,
serviceAccount: tc.state.GCPServiceAccount,
healthCheck: tc.state.GCPHealthCheck,
backendService: tc.state.GCPBackendService,
forwardingRule: tc.state.GCPForwardingRule,
}
if tc.wantErr {
_, err := client.GetState()
@ -592,6 +742,9 @@ func TestSetStateCloudProvider(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
}
assert.Error(client.SetState(stateMissingCloudProvider))
stateIncorrectCloudProvider := state.ConstellationState{
@ -620,6 +773,9 @@ func TestSetStateCloudProvider(t *testing.T) {
GCPFirewalls: []string{"fw-1", "fw-2"},
GCPNodeInstanceTemplate: "temp-id",
GCPCoordinatorInstanceTemplate: "temp-id",
GCPBackendService: "backend-service-id",
GCPHealthCheck: "health-check-id",
GCPForwardingRule: "forwarding-rule-id",
}
assert.Error(client.SetState(stateIncorrectCloudProvider))
}

View file

@ -46,6 +46,78 @@ func (c *firewallsClient) Insert(ctx context.Context, req *computepb.InsertFirew
return c.FirewallsClient.Insert(ctx, req)
}
type forwardingRulesClient struct {
*compute.ForwardingRulesClient
}
func (c *forwardingRulesClient) Close() error {
return c.ForwardingRulesClient.Close()
}
func (c *forwardingRulesClient) Delete(ctx context.Context, req *computepb.DeleteForwardingRuleRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.ForwardingRulesClient.Delete(ctx, req)
}
func (c *forwardingRulesClient) Insert(ctx context.Context, req *computepb.InsertForwardingRuleRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.ForwardingRulesClient.Insert(ctx, req)
}
func (c *forwardingRulesClient) Get(ctx context.Context, req *computepb.GetForwardingRuleRequest,
opts ...gax.CallOption,
) (*computepb.ForwardingRule, error) {
return c.ForwardingRulesClient.Get(ctx, req)
}
func (c *forwardingRulesClient) SetLabels(ctx context.Context, req *computepb.SetLabelsForwardingRuleRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.ForwardingRulesClient.SetLabels(ctx, req)
}
type backendServicesClient struct {
*compute.RegionBackendServicesClient
}
func (c *backendServicesClient) Close() error {
return c.RegionBackendServicesClient.Close()
}
func (c *backendServicesClient) Insert(ctx context.Context, req *computepb.InsertRegionBackendServiceRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.RegionBackendServicesClient.Insert(ctx, req)
}
func (c *backendServicesClient) Delete(ctx context.Context, req *computepb.DeleteRegionBackendServiceRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.RegionBackendServicesClient.Delete(ctx, req)
}
type healthChecksClient struct {
*compute.RegionHealthChecksClient
}
func (c *healthChecksClient) Close() error {
return c.RegionHealthChecksClient.Close()
}
func (c *healthChecksClient) Delete(ctx context.Context, req *computepb.DeleteRegionHealthCheckRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.RegionHealthChecksClient.Delete(ctx, req)
}
func (c *healthChecksClient) Insert(ctx context.Context, req *computepb.InsertRegionHealthCheckRequest,
opts ...gax.CallOption,
) (Operation, error) {
return c.RegionHealthChecksClient.Insert(ctx, req)
}
type networksClient struct {
*compute.NetworksClient
}

View file

@ -3,8 +3,10 @@ package client
import (
"context"
"errors"
"fmt"
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
"google.golang.org/genproto/googleapis/cloud/compute/v1"
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
"google.golang.org/protobuf/proto"
)
@ -197,3 +199,136 @@ func (c *Client) terminateSubnet(ctx context.Context) error {
}
return c.waitForOperations(ctx, []Operation{op})
}
// CreateLoadBalancer creates a load balancer.
func (c *Client) CreateLoadBalancer(ctx context.Context) error {
c.healthCheck = c.name + "-" + c.uid
resp, err := c.healthChecksAPI.Insert(ctx, &computepb.InsertRegionHealthCheckRequest{
Project: c.project,
Region: c.region,
HealthCheckResource: &computepb.HealthCheck{
Name: proto.String(c.healthCheck),
Type: proto.String(compute.HealthCheck_Type_name[int32(compute.HealthCheck_TCP)]),
CheckIntervalSec: proto.Int32(1),
TimeoutSec: proto.Int32(1),
TcpHealthCheck: &computepb.TCPHealthCheck{
Port: proto.Int32(6443),
},
},
})
if err != nil {
return err
}
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
return err
}
c.backendService = c.name + "-" + c.uid
resp, err = c.backendServicesAPI.Insert(ctx, &computepb.InsertRegionBackendServiceRequest{
Project: c.project,
Region: c.region,
BackendServiceResource: &computepb.BackendService{
Name: proto.String(c.backendService),
Protocol: proto.String(compute.BackendService_Protocol_name[int32(compute.BackendService_TCP)]),
LoadBalancingScheme: proto.String(computepb.BackendService_LoadBalancingScheme_name[int32(compute.BackendService_EXTERNAL)]),
TimeoutSec: proto.Int32(10),
HealthChecks: []string{"https://www.googleapis.com/compute/v1/projects/" + c.project + "/regions/" + c.region + "/healthChecks/" + c.healthCheck},
Backends: []*computepb.Backend{
{
BalancingMode: proto.String(computepb.Backend_BalancingMode_name[int32(compute.Backend_CONNECTION)]),
Group: proto.String("https://www.googleapis.com/compute/v1/projects/" + c.project + "/zones/" + c.zone + "/instanceGroups/" + c.coordinatorInstanceGroup),
},
},
},
})
if err != nil {
return err
}
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
return err
}
c.forwardingRule = c.name + "-" + c.uid
resp, err = c.forwardingRulesAPI.Insert(ctx, &computepb.InsertForwardingRuleRequest{
Project: c.project,
Region: c.region,
ForwardingRuleResource: &computepb.ForwardingRule{
Name: proto.String(c.forwardingRule),
IPProtocol: proto.String(compute.ForwardingRule_IPProtocolEnum_name[int32(compute.ForwardingRule_TCP)]),
LoadBalancingScheme: proto.String(compute.ForwardingRule_LoadBalancingScheme_name[int32(compute.ForwardingRule_EXTERNAL)]),
Ports: []string{"6443", "9000"},
BackendService: proto.String("https://www.googleapis.com/compute/v1/projects/" + c.project + "/regions/" + c.region + "/backendServices/" + c.backendService),
},
})
if err != nil {
return err
}
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
return err
}
forwardingRule, err := c.forwardingRulesAPI.Get(ctx, &computepb.GetForwardingRuleRequest{
Project: c.project,
Region: c.region,
ForwardingRule: c.forwardingRule,
})
if err != nil {
return err
}
if forwardingRule.LabelFingerprint == nil {
return fmt.Errorf("forwarding rule %s has no label fingerprint", c.forwardingRule)
}
resp, err = c.forwardingRulesAPI.SetLabels(ctx, &computepb.SetLabelsForwardingRuleRequest{
Project: c.project,
Region: c.region,
Resource: c.forwardingRule,
RegionSetLabelsRequestResource: &computepb.RegionSetLabelsRequest{
Labels: map[string]string{"constellation-uid": c.uid},
LabelFingerprint: forwardingRule.LabelFingerprint,
},
})
if err != nil {
return err
}
return c.waitForOperations(ctx, []Operation{resp})
}
// TerminteLoadBalancer removes the load balancer and its associated resources.
func (c *Client) TerminateLoadBalancer(ctx context.Context) error {
resp, err := c.forwardingRulesAPI.Delete(ctx, &computepb.DeleteForwardingRuleRequest{
Project: c.project,
Region: c.region,
ForwardingRule: c.forwardingRule,
})
if err != nil {
return err
}
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
return err
}
resp, err = c.backendServicesAPI.Delete(ctx, &computepb.DeleteRegionBackendServiceRequest{
Project: c.project,
Region: c.region,
BackendService: c.backendService,
})
if err != nil {
return err
}
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
return err
}
resp, err = c.healthChecksAPI.Delete(ctx, &computepb.DeleteRegionHealthCheckRequest{
Project: c.project,
Region: c.region,
HealthCheck: c.healthCheck,
})
if err != nil {
return err
}
return c.waitForOperations(ctx, []Operation{resp})
}

View file

@ -7,6 +7,8 @@ import (
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
"github.com/stretchr/testify/assert"
"google.golang.org/genproto/googleapis/cloud/compute/v1"
"google.golang.org/protobuf/proto"
)
func TestCreateVPCs(t *testing.T) {
@ -307,3 +309,163 @@ func TestTerminateFirewall(t *testing.T) {
})
}
}
func TestCreateLoadBalancer(t *testing.T) {
someErr := errors.New("failed")
testCases := map[string]struct {
operationRegionAPI operationRegionAPI
healthChecksAPI healthChecksAPI
backendServicesAPI backendServicesAPI
forwardingRulesAPI forwardingRulesAPI
wantErr bool
}{
"successful create": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{forwardingRule: &compute.ForwardingRule{LabelFingerprint: proto.String("fingerprint")}},
operationRegionAPI: stubOperationRegionAPI{},
},
"CreateLoadBalancer fails when getting forwarding rule": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{getErr: someErr},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"CreateLoadBalancer fails when label fingerprint is missing": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{forwardingRule: &compute.ForwardingRule{}},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"CreateLoadBalancer fails when creating health check": {
healthChecksAPI: stubHealthChecksAPI{insertErr: someErr},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{forwardingRule: &compute.ForwardingRule{LabelFingerprint: proto.String("fingerprint")}},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"CreateLoadBalancer fails when creating backend service": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{insertErr: someErr},
forwardingRulesAPI: stubForwardingRulesAPI{},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"CreateLoadBalancer fails when creating forwarding rule": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{insertErr: someErr},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"CreateLoadBalancer fails when waiting on operation": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{forwardingRule: &compute.ForwardingRule{LabelFingerprint: proto.String("fingerprint")}},
operationRegionAPI: stubOperationRegionAPI{waitErr: someErr},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
client := Client{
project: "project",
zone: "zone",
name: "name",
uid: "uid",
backendServicesAPI: tc.backendServicesAPI,
forwardingRulesAPI: tc.forwardingRulesAPI,
healthChecksAPI: tc.healthChecksAPI,
operationRegionAPI: tc.operationRegionAPI,
}
if tc.wantErr {
assert.Error(client.CreateLoadBalancer(ctx))
} else {
assert.NoError(client.CreateLoadBalancer(ctx))
assert.NotEmpty(client.healthCheck)
assert.NotEmpty(client.backendService)
assert.NotEmpty(client.forwardingRule)
}
})
}
}
func TestTerminateLoadBalancer(t *testing.T) {
someErr := errors.New("failed")
testCases := map[string]struct {
operationRegionAPI operationRegionAPI
healthChecksAPI healthChecksAPI
backendServicesAPI backendServicesAPI
forwardingRulesAPI forwardingRulesAPI
wantErr bool
}{
"successful terminate": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{},
operationRegionAPI: stubOperationRegionAPI{},
},
"TerminateLoadBalancer fails when deleting health check": {
healthChecksAPI: stubHealthChecksAPI{deleteErr: someErr},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"TerminateLoadBalancer fails when deleting backend service": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{deleteErr: someErr},
forwardingRulesAPI: stubForwardingRulesAPI{},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"TerminateLoadBalancer fails when deleting forwarding rule": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{deleteErr: someErr},
operationRegionAPI: stubOperationRegionAPI{},
wantErr: true,
},
"TerminateLoadBalancer fails when waiting on operation": {
healthChecksAPI: stubHealthChecksAPI{},
backendServicesAPI: stubBackendServicesAPI{},
forwardingRulesAPI: stubForwardingRulesAPI{},
operationRegionAPI: stubOperationRegionAPI{waitErr: someErr},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
client := Client{
project: "project",
zone: "zone",
name: "name",
uid: "uid",
backendServicesAPI: tc.backendServicesAPI,
forwardingRulesAPI: tc.forwardingRulesAPI,
healthChecksAPI: tc.healthChecksAPI,
operationRegionAPI: tc.operationRegionAPI,
}
if tc.wantErr {
assert.Error(client.TerminateLoadBalancer(ctx))
} else {
assert.NoError(client.TerminateLoadBalancer(ctx))
assert.Empty(client.healthCheck)
assert.Empty(client.backendService)
assert.Empty(client.forwardingRule)
}
})
}
}