mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-26 16:09:45 -05:00
add gcp loadbalancer
This commit is contained in:
parent
1e11188dac
commit
e13f4d84c3
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
- Early boot logging for Cloud Provider: GCP & Azure
|
- Early boot logging for Cloud Provider: GCP & Azure
|
||||||
- Added `constellation-access-manager`, allowing users to manage SSH users over a ConfigMap. This allows persistent & dynamic management of SSH users on multiple nodes, even after a reboot.
|
- Added `constellation-access-manager`, allowing users to manage SSH users over a ConfigMap. This allows persistent & dynamic management of SSH users on multiple nodes, even after a reboot.
|
||||||
|
- GCP-native Kubernetes load balancing
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -14,9 +14,11 @@ type gcpclient interface {
|
|||||||
CreateVPCs(ctx context.Context) error
|
CreateVPCs(ctx context.Context) error
|
||||||
CreateFirewall(ctx context.Context, input gcpcl.FirewallInput) error
|
CreateFirewall(ctx context.Context, input gcpcl.FirewallInput) error
|
||||||
CreateInstances(ctx context.Context, input gcpcl.CreateInstancesInput) error
|
CreateInstances(ctx context.Context, input gcpcl.CreateInstancesInput) error
|
||||||
|
CreateLoadBalancer(ctx context.Context) error
|
||||||
CreateServiceAccount(ctx context.Context, input gcpcl.ServiceAccountInput) (string, error)
|
CreateServiceAccount(ctx context.Context, input gcpcl.ServiceAccountInput) (string, error)
|
||||||
TerminateFirewall(ctx context.Context) error
|
TerminateFirewall(ctx context.Context) error
|
||||||
TerminateVPCs(context.Context) error
|
TerminateVPCs(context.Context) error
|
||||||
|
TerminateLoadBalancer(context.Context) error
|
||||||
TerminateInstances(context.Context) error
|
TerminateInstances(context.Context) error
|
||||||
TerminateServiceAccount(ctx context.Context) error
|
TerminateServiceAccount(ctx context.Context) error
|
||||||
Close() error
|
Close() error
|
||||||
|
@ -241,6 +241,11 @@ type fakeGcpClient struct {
|
|||||||
name string
|
name string
|
||||||
zone string
|
zone string
|
||||||
serviceAccount string
|
serviceAccount string
|
||||||
|
|
||||||
|
// loadbalancer
|
||||||
|
healthCheck string
|
||||||
|
backendService string
|
||||||
|
forwardingRule string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeGcpClient) GetState() (state.ConstellationState, error) {
|
func (c *fakeGcpClient) GetState() (state.ConstellationState, error) {
|
||||||
@ -255,6 +260,9 @@ func (c *fakeGcpClient) GetState() (state.ConstellationState, error) {
|
|||||||
GCPNetwork: c.network,
|
GCPNetwork: c.network,
|
||||||
GCPSubnetwork: c.subnetwork,
|
GCPSubnetwork: c.subnetwork,
|
||||||
GCPFirewalls: c.firewalls,
|
GCPFirewalls: c.firewalls,
|
||||||
|
GCPBackendService: c.backendService,
|
||||||
|
GCPHealthCheck: c.healthCheck,
|
||||||
|
GCPForwardingRule: c.forwardingRule,
|
||||||
GCPProject: c.project,
|
GCPProject: c.project,
|
||||||
Name: c.name,
|
Name: c.name,
|
||||||
UID: c.uid,
|
UID: c.uid,
|
||||||
@ -279,6 +287,9 @@ func (c *fakeGcpClient) SetState(stat state.ConstellationState) error {
|
|||||||
c.uid = stat.UID
|
c.uid = stat.UID
|
||||||
c.zone = stat.GCPZone
|
c.zone = stat.GCPZone
|
||||||
c.serviceAccount = stat.GCPServiceAccount
|
c.serviceAccount = stat.GCPServiceAccount
|
||||||
|
c.healthCheck = stat.GCPHealthCheck
|
||||||
|
c.backendService = stat.GCPBackendService
|
||||||
|
c.forwardingRule = stat.GCPForwardingRule
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +343,13 @@ func (c *fakeGcpClient) CreateServiceAccount(ctx context.Context, input gcpcl.Se
|
|||||||
}.ToCloudServiceAccountURI(), nil
|
}.ToCloudServiceAccountURI(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fakeGcpClient) CreateLoadBalancer(ctx context.Context) error {
|
||||||
|
c.healthCheck = "health-check"
|
||||||
|
c.backendService = "backend-service"
|
||||||
|
c.forwardingRule = "forwarding-rule"
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *fakeGcpClient) TerminateFirewall(ctx context.Context) error {
|
func (c *fakeGcpClient) TerminateFirewall(ctx context.Context) error {
|
||||||
if len(c.firewalls) == 0 {
|
if len(c.firewalls) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -364,6 +382,13 @@ func (c *fakeGcpClient) TerminateServiceAccount(context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fakeGcpClient) TerminateLoadBalancer(context.Context) error {
|
||||||
|
c.healthCheck = ""
|
||||||
|
c.backendService = ""
|
||||||
|
c.forwardingRule = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *fakeGcpClient) Close() error {
|
func (c *fakeGcpClient) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -381,10 +406,12 @@ type stubGcpClient struct {
|
|||||||
createFirewallErr error
|
createFirewallErr error
|
||||||
createInstancesErr error
|
createInstancesErr error
|
||||||
createServiceAccountErr error
|
createServiceAccountErr error
|
||||||
|
createLoadBalancerErr error
|
||||||
terminateFirewallErr error
|
terminateFirewallErr error
|
||||||
terminateVPCsErr error
|
terminateVPCsErr error
|
||||||
terminateInstancesErr error
|
terminateInstancesErr error
|
||||||
terminateServiceAccountErr error
|
terminateServiceAccountErr error
|
||||||
|
terminateLoadBalancerErr error
|
||||||
closeErr error
|
closeErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,6 +439,10 @@ func (c *stubGcpClient) CreateServiceAccount(ctx context.Context, input gcpcl.Se
|
|||||||
return gcpshared.ServiceAccountKey{}.ToCloudServiceAccountURI(), c.createServiceAccountErr
|
return gcpshared.ServiceAccountKey{}.ToCloudServiceAccountURI(), c.createServiceAccountErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *stubGcpClient) CreateLoadBalancer(ctx context.Context) error {
|
||||||
|
return c.createLoadBalancerErr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *stubGcpClient) TerminateFirewall(ctx context.Context) error {
|
func (c *stubGcpClient) TerminateFirewall(ctx context.Context) error {
|
||||||
c.terminateFirewallCalled = true
|
c.terminateFirewallCalled = true
|
||||||
return c.terminateFirewallErr
|
return c.terminateFirewallErr
|
||||||
@ -432,6 +463,10 @@ func (c *stubGcpClient) TerminateServiceAccount(context.Context) error {
|
|||||||
return c.terminateServiceAccountErr
|
return c.terminateServiceAccountErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *stubGcpClient) TerminateLoadBalancer(context.Context) error {
|
||||||
|
return c.terminateLoadBalancerErr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *stubGcpClient) Close() error {
|
func (c *stubGcpClient) Close() error {
|
||||||
c.closeCalled = true
|
c.closeCalled = true
|
||||||
return c.closeErr
|
return c.closeErr
|
||||||
|
@ -132,6 +132,10 @@ func (c *Creator) createGCP(ctx context.Context, cl gcpclient, config *config.Co
|
|||||||
return state.ConstellationState{}, err
|
return state.ConstellationState{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := cl.CreateLoadBalancer(ctx); err != nil {
|
||||||
|
return state.ConstellationState{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return cl.GetState()
|
return cl.GetState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,9 @@ func TestCreator(t *testing.T) {
|
|||||||
GCPCoordinatorInstanceTemplate: "coordinator-template",
|
GCPCoordinatorInstanceTemplate: "coordinator-template",
|
||||||
GCPNetwork: "network",
|
GCPNetwork: "network",
|
||||||
GCPSubnetwork: "subnetwork",
|
GCPSubnetwork: "subnetwork",
|
||||||
|
GCPBackendService: "backend-service",
|
||||||
|
GCPHealthCheck: "health-check",
|
||||||
|
GCPForwardingRule: "forwarding-rule",
|
||||||
GCPFirewalls: []string{
|
GCPFirewalls: []string{
|
||||||
"coordinator", "wireguard", "ssh", "nodeport", "kubernetes",
|
"coordinator", "wireguard", "ssh", "nodeport", "kubernetes",
|
||||||
"allow-cluster-internal-tcp", "allow-cluster-internal-udp", "allow-cluster-internal-icmp",
|
"allow-cluster-internal-tcp", "allow-cluster-internal-udp", "allow-cluster-internal-icmp",
|
||||||
@ -103,6 +106,13 @@ func TestCreator(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
wantRollback: true,
|
wantRollback: true,
|
||||||
},
|
},
|
||||||
|
"gcp CreateLoadBalancer error": {
|
||||||
|
gcpclient: &stubGcpClient{createLoadBalancerErr: someErr},
|
||||||
|
provider: cloudprovider.GCP,
|
||||||
|
config: config.Default(),
|
||||||
|
wantErr: true,
|
||||||
|
wantRollback: true,
|
||||||
|
},
|
||||||
"azure": {
|
"azure": {
|
||||||
azureclient: &fakeAzureClient{},
|
azureclient: &fakeAzureClient{},
|
||||||
provider: cloudprovider.Azure,
|
provider: cloudprovider.Azure,
|
||||||
|
@ -34,6 +34,7 @@ type rollbackerGCP struct {
|
|||||||
|
|
||||||
func (r *rollbackerGCP) rollback(ctx context.Context) error {
|
func (r *rollbackerGCP) rollback(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
|
err = multierr.Append(err, r.client.TerminateLoadBalancer(ctx))
|
||||||
err = multierr.Append(err, r.client.TerminateInstances(ctx))
|
err = multierr.Append(err, r.client.TerminateInstances(ctx))
|
||||||
err = multierr.Append(err, r.client.TerminateFirewall(ctx))
|
err = multierr.Append(err, r.client.TerminateFirewall(ctx))
|
||||||
err = multierr.Append(err, r.client.TerminateVPCs(ctx))
|
err = multierr.Append(err, r.client.TerminateVPCs(ctx))
|
||||||
|
@ -55,6 +55,9 @@ func (t *Terminator) terminateGCP(ctx context.Context, cl gcpclient, state state
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := cl.TerminateLoadBalancer(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := cl.TerminateInstances(ctx); err != nil {
|
if err := cl.TerminateInstances(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,34 @@ type firewallsAPI interface {
|
|||||||
opts ...gax.CallOption) (Operation, error)
|
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 {
|
type networksAPI interface {
|
||||||
Close() error
|
Close() error
|
||||||
Delete(ctx context.Context, req *computepb.DeleteNetworkRequest,
|
Delete(ctx context.Context, req *computepb.DeleteNetworkRequest,
|
||||||
|
@ -219,6 +219,143 @@ func (a stubSubnetworksAPI) Delete(ctx context.Context, req *computepb.DeleteSub
|
|||||||
}, nil
|
}, 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 {
|
type stubInstanceTemplateAPI struct {
|
||||||
deleteErr error
|
deleteErr error
|
||||||
insertErr error
|
insertErr error
|
||||||
|
@ -25,6 +25,9 @@ type Client struct {
|
|||||||
networksAPI
|
networksAPI
|
||||||
subnetworksAPI
|
subnetworksAPI
|
||||||
firewallsAPI
|
firewallsAPI
|
||||||
|
forwardingRulesAPI
|
||||||
|
backendServicesAPI
|
||||||
|
healthChecksAPI
|
||||||
instanceTemplateAPI
|
instanceTemplateAPI
|
||||||
instanceGroupManagersAPI
|
instanceGroupManagersAPI
|
||||||
iamAPI
|
iamAPI
|
||||||
@ -47,6 +50,11 @@ type Client struct {
|
|||||||
zone string
|
zone string
|
||||||
region string
|
region string
|
||||||
serviceAccount string
|
serviceAccount string
|
||||||
|
|
||||||
|
// loadbalancer
|
||||||
|
healthCheck string
|
||||||
|
backendService string
|
||||||
|
forwardingRule string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromDefault creates an uninitialized client.
|
// NewFromDefault creates an uninitialized client.
|
||||||
@ -92,7 +100,31 @@ func NewFromDefault(ctx context.Context) (*Client, error) {
|
|||||||
_ = closeAll(closers)
|
_ = closeAll(closers)
|
||||||
return nil, err
|
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)
|
templAPI, err := compute.NewInstanceTemplatesRESTClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = closeAll(closers)
|
_ = closeAll(closers)
|
||||||
@ -124,6 +156,9 @@ func NewFromDefault(ctx context.Context) (*Client, error) {
|
|||||||
networksAPI: &networksClient{netAPI},
|
networksAPI: &networksClient{netAPI},
|
||||||
subnetworksAPI: &subnetworksClient{subnetAPI},
|
subnetworksAPI: &subnetworksClient{subnetAPI},
|
||||||
firewallsAPI: &firewallsClient{fwAPI},
|
firewallsAPI: &firewallsClient{fwAPI},
|
||||||
|
forwardingRulesAPI: &forwardingRulesClient{forwardingRulesAPI},
|
||||||
|
backendServicesAPI: &backendServicesClient{backendServicesAPI},
|
||||||
|
healthChecksAPI: &healthChecksClient{healthChecksAPI},
|
||||||
instanceTemplateAPI: &instanceTemplateClient{templAPI},
|
instanceTemplateAPI: &instanceTemplateClient{templAPI},
|
||||||
instanceGroupManagersAPI: &instanceGroupManagersClient{groupAPI},
|
instanceGroupManagersAPI: &instanceGroupManagersClient{groupAPI},
|
||||||
iamAPI: &iamClient{iamAPI},
|
iamAPI: &iamClient{iamAPI},
|
||||||
@ -147,12 +182,19 @@ func NewInitialized(ctx context.Context, project, zone, region, name string) (*C
|
|||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
closers := []closer{
|
closers := []closer{
|
||||||
c.instanceAPI,
|
c.instanceAPI,
|
||||||
|
c.operationRegionAPI,
|
||||||
c.operationZoneAPI,
|
c.operationZoneAPI,
|
||||||
c.operationGlobalAPI,
|
c.operationGlobalAPI,
|
||||||
c.networksAPI,
|
c.networksAPI,
|
||||||
|
c.subnetworksAPI,
|
||||||
c.firewallsAPI,
|
c.firewallsAPI,
|
||||||
|
c.forwardingRulesAPI,
|
||||||
|
c.backendServicesAPI,
|
||||||
|
c.healthChecksAPI,
|
||||||
c.instanceTemplateAPI,
|
c.instanceTemplateAPI,
|
||||||
c.instanceGroupManagersAPI,
|
c.instanceGroupManagersAPI,
|
||||||
|
c.iamAPI,
|
||||||
|
c.projectsAPI,
|
||||||
}
|
}
|
||||||
return closeAll(closers)
|
return closeAll(closers)
|
||||||
}
|
}
|
||||||
@ -246,6 +288,21 @@ func (c *Client) GetState() (state.ConstellationState, error) {
|
|||||||
}
|
}
|
||||||
stat.GCPCoordinatorInstanceTemplate = c.coordinatorTemplate
|
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
|
// service account does not have to be set at all times
|
||||||
stat.GCPServiceAccount = c.serviceAccount
|
stat.GCPServiceAccount = c.serviceAccount
|
||||||
|
|
||||||
@ -327,6 +384,21 @@ func (c *Client) SetState(stat state.ConstellationState) error {
|
|||||||
}
|
}
|
||||||
c.coordinatorTemplate = stat.GCPCoordinatorInstanceTemplate
|
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
|
// service account does not have to be set at all times
|
||||||
c.serviceAccount = stat.GCPServiceAccount
|
c.serviceAccount = stat.GCPServiceAccount
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
GCPServiceAccount: "service-account",
|
GCPServiceAccount: "service-account",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"missing nodes": {
|
"missing nodes": {
|
||||||
@ -67,6 +70,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -91,6 +97,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -120,6 +129,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -149,6 +161,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -178,6 +193,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -207,6 +225,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -236,6 +257,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -264,6 +288,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -293,6 +320,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -322,6 +352,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPSubnetwork: "subnet-id",
|
GCPSubnetwork: "subnet-id",
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -350,6 +383,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -379,6 +415,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -408,6 +447,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -437,6 +479,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -466,6 +511,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPSubnetwork: "subnet-id",
|
GCPSubnetwork: "subnet-id",
|
||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -495,6 +543,105 @@ func TestSetGetState(t *testing.T) {
|
|||||||
GCPSubnetwork: "subnet-id",
|
GCPSubnetwork: "subnet-id",
|
||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
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,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -549,6 +696,9 @@ func TestSetGetState(t *testing.T) {
|
|||||||
nodeTemplate: tc.state.GCPNodeInstanceTemplate,
|
nodeTemplate: tc.state.GCPNodeInstanceTemplate,
|
||||||
coordinatorTemplate: tc.state.GCPCoordinatorInstanceTemplate,
|
coordinatorTemplate: tc.state.GCPCoordinatorInstanceTemplate,
|
||||||
serviceAccount: tc.state.GCPServiceAccount,
|
serviceAccount: tc.state.GCPServiceAccount,
|
||||||
|
healthCheck: tc.state.GCPHealthCheck,
|
||||||
|
backendService: tc.state.GCPBackendService,
|
||||||
|
forwardingRule: tc.state.GCPForwardingRule,
|
||||||
}
|
}
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
_, err := client.GetState()
|
_, err := client.GetState()
|
||||||
@ -592,6 +742,9 @@ func TestSetStateCloudProvider(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
}
|
}
|
||||||
assert.Error(client.SetState(stateMissingCloudProvider))
|
assert.Error(client.SetState(stateMissingCloudProvider))
|
||||||
stateIncorrectCloudProvider := state.ConstellationState{
|
stateIncorrectCloudProvider := state.ConstellationState{
|
||||||
@ -620,6 +773,9 @@ func TestSetStateCloudProvider(t *testing.T) {
|
|||||||
GCPFirewalls: []string{"fw-1", "fw-2"},
|
GCPFirewalls: []string{"fw-1", "fw-2"},
|
||||||
GCPNodeInstanceTemplate: "temp-id",
|
GCPNodeInstanceTemplate: "temp-id",
|
||||||
GCPCoordinatorInstanceTemplate: "temp-id",
|
GCPCoordinatorInstanceTemplate: "temp-id",
|
||||||
|
GCPBackendService: "backend-service-id",
|
||||||
|
GCPHealthCheck: "health-check-id",
|
||||||
|
GCPForwardingRule: "forwarding-rule-id",
|
||||||
}
|
}
|
||||||
assert.Error(client.SetState(stateIncorrectCloudProvider))
|
assert.Error(client.SetState(stateIncorrectCloudProvider))
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,78 @@ func (c *firewallsClient) Insert(ctx context.Context, req *computepb.InsertFirew
|
|||||||
return c.FirewallsClient.Insert(ctx, req)
|
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 {
|
type networksClient struct {
|
||||||
*compute.NetworksClient
|
*compute.NetworksClient
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
|
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
|
||||||
|
"google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||||
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
@ -197,3 +199,136 @@ func (c *Client) terminateSubnet(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
return c.waitForOperations(ctx, []Operation{op})
|
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})
|
||||||
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
|
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateVPCs(t *testing.T) {
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,11 @@ type subnetworkAPI interface {
|
|||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type forwardingRulesAPI interface {
|
||||||
|
List(ctx context.Context, req *computepb.ListForwardingRulesRequest, opts ...gax.CallOption) ForwardingRuleIterator
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
type metadataAPI interface {
|
type metadataAPI interface {
|
||||||
InstanceAttributeValue(attr string) (string, error)
|
InstanceAttributeValue(attr string) (string, error)
|
||||||
ProjectID() (string, error)
|
ProjectID() (string, error)
|
||||||
@ -40,3 +45,7 @@ type InstanceIterator interface {
|
|||||||
type SubnetworkIterator interface {
|
type SubnetworkIterator interface {
|
||||||
Next() (*computepb.Subnetwork, error)
|
Next() (*computepb.Subnetwork, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ForwardingRuleIterator interface {
|
||||||
|
Next() (*computepb.ForwardingRule, error)
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package gcp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
compute "cloud.google.com/go/compute/apiv1"
|
compute "cloud.google.com/go/compute/apiv1"
|
||||||
@ -17,11 +18,14 @@ import (
|
|||||||
|
|
||||||
const gcpSSHMetadataKey = "ssh-keys"
|
const gcpSSHMetadataKey = "ssh-keys"
|
||||||
|
|
||||||
|
var zoneFromRegionRegex = regexp.MustCompile("([a-z]*-[a-z]*[0-9])")
|
||||||
|
|
||||||
// Client implements the gcp.API interface.
|
// Client implements the gcp.API interface.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
instanceAPI
|
instanceAPI
|
||||||
subnetworkAPI
|
subnetworkAPI
|
||||||
metadataAPI
|
metadataAPI
|
||||||
|
forwardingRulesAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new Client.
|
// NewClient creates a new Client.
|
||||||
@ -34,7 +38,16 @@ func NewClient(ctx context.Context) (*Client, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Client{instanceAPI: &instanceClient{insAPI}, subnetworkAPI: &subnetworkClient{subnetAPI}, metadataAPI: &metadataClient{}}, nil
|
forwardingRulesAPI, err := compute.NewForwardingRulesRESTClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
instanceAPI: &instanceClient{insAPI},
|
||||||
|
subnetworkAPI: &subnetworkClient{subnetAPI},
|
||||||
|
forwardingRulesAPI: &forwardingRulesClient{forwardingRulesAPI},
|
||||||
|
metadataAPI: &metadataClient{},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveInstances returns list of instances including their ips and metadata.
|
// RetrieveInstances returns list of instances including their ips and metadata.
|
||||||
@ -178,8 +191,10 @@ func (c *Client) RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone,
|
|||||||
// convert:
|
// convert:
|
||||||
// zone --> region
|
// zone --> region
|
||||||
// europe-west3-b --> europe-west3
|
// europe-west3-b --> europe-west3
|
||||||
regionParts := strings.Split(zone, "-")
|
region := zoneFromRegionRegex.FindString(zone)
|
||||||
region := strings.TrimSuffix(zone, "-"+regionParts[len(regionParts)-1])
|
if region == "" {
|
||||||
|
return "", fmt.Errorf("invalid zone %s", zone)
|
||||||
|
}
|
||||||
|
|
||||||
req := &computepb.GetSubnetworkRequest{
|
req := &computepb.GetSubnetworkRequest{
|
||||||
Project: project,
|
Project: project,
|
||||||
@ -196,11 +211,47 @@ func (c *Client) RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone,
|
|||||||
return *subnetwork.IpCidrRange, nil
|
return *subnetwork.IpCidrRange, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RetrieveLoadBalancerIP returns the IP address of the load balancer specified by project, zone and loadBalancerName.
|
||||||
|
func (c *Client) RetrieveLoadBalancerIP(ctx context.Context, project, zone string) (string, error) {
|
||||||
|
uid, err := c.uid()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
region := zoneFromRegionRegex.FindString(zone)
|
||||||
|
if region == "" {
|
||||||
|
return "", fmt.Errorf("invalid zone %s", zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &computepb.ListForwardingRulesRequest{
|
||||||
|
Region: region,
|
||||||
|
Project: project,
|
||||||
|
}
|
||||||
|
iter := c.forwardingRulesAPI.List(ctx, req)
|
||||||
|
for {
|
||||||
|
resp, err := iter.Next()
|
||||||
|
if err == iterator.Done {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("retrieving load balancer IP failed: %w", err)
|
||||||
|
}
|
||||||
|
if resp.Labels["constellation-uid"] == uid {
|
||||||
|
return *resp.IPAddress, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("retrieving load balancer IP failed: load balancer not found")
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the instanceAPI client.
|
// Close closes the instanceAPI client.
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
if err := c.subnetworkAPI.Close(); err != nil {
|
if err := c.subnetworkAPI.Close(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := c.forwardingRulesAPI.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return c.instanceAPI.Close()
|
return c.instanceAPI.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +756,7 @@ func TestRetrieveSubnetworkAliasCIDR(t *testing.T) {
|
|||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
client := Client{instanceAPI: tc.stubInstancesClient, subnetworkAPI: tc.stubSubnetworksClient}
|
client := Client{instanceAPI: tc.stubInstancesClient, subnetworkAPI: tc.stubSubnetworksClient}
|
||||||
aliasCIDR, err := client.RetrieveSubnetworkAliasCIDR(context.Background(), "project", "zone", "subnetwork")
|
aliasCIDR, err := client.RetrieveSubnetworkAliasCIDR(context.Background(), "project", "us-central1-a", "subnetwork")
|
||||||
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
@ -768,18 +768,106 @@ func TestRetrieveSubnetworkAliasCIDR(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRetrieveLoadBalancerIP(t *testing.T) {
|
||||||
|
loadBalancerIP := "192.0.2.1"
|
||||||
|
uid := "uid"
|
||||||
|
someErr := errors.New("some error")
|
||||||
|
testCases := map[string]struct {
|
||||||
|
stubForwardingRulesClient stubForwardingRulesClient
|
||||||
|
stubMetadataClient stubMetadataClient
|
||||||
|
wantLoadBalancerIP string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
"RetrieveSubnetworkAliasCIDR works": {
|
||||||
|
stubMetadataClient: stubMetadataClient{InstanceValue: uid},
|
||||||
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
|
rules: []*computepb.ForwardingRule{
|
||||||
|
{
|
||||||
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
|
Labels: map[string]string{"constellation-uid": uid},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantLoadBalancerIP: loadBalancerIP,
|
||||||
|
},
|
||||||
|
"RetrieveSubnetworkAliasCIDR fails when no matching load balancers exists": {
|
||||||
|
stubMetadataClient: stubMetadataClient{InstanceValue: uid},
|
||||||
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
|
rules: []*computepb.ForwardingRule{
|
||||||
|
{
|
||||||
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"RetrieveSubnetworkAliasCIDR fails when retrieving uid": {
|
||||||
|
stubMetadataClient: stubMetadataClient{InstanceErr: someErr},
|
||||||
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
|
rules: []*computepb.ForwardingRule{
|
||||||
|
{
|
||||||
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
|
Labels: map[string]string{"constellation-uid": uid},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"RetrieveSubnetworkAliasCIDR fails when retrieving loadbalancer IP": {
|
||||||
|
stubMetadataClient: stubMetadataClient{},
|
||||||
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
|
nextErr: someErr,
|
||||||
|
rules: []*computepb.ForwardingRule{
|
||||||
|
{
|
||||||
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
|
Labels: map[string]string{"constellation-uid": uid},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
client := Client{forwardingRulesAPI: tc.stubForwardingRulesClient, metadataAPI: tc.stubMetadataClient}
|
||||||
|
aliasCIDR, err := client.RetrieveLoadBalancerIP(context.Background(), "project", "us-central1-a")
|
||||||
|
|
||||||
|
if tc.wantErr {
|
||||||
|
assert.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(err)
|
||||||
|
assert.Equal(tc.wantLoadBalancerIP, aliasCIDR)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestClose(t *testing.T) {
|
func TestClose(t *testing.T) {
|
||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
|
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
client := Client{instanceAPI: stubInstancesClient{}, subnetworkAPI: stubSubnetworksClient{}}
|
client := Client{instanceAPI: stubInstancesClient{}, subnetworkAPI: stubSubnetworksClient{}, forwardingRulesAPI: stubForwardingRulesClient{}}
|
||||||
assert.NoError(client.Close())
|
assert.NoError(client.Close())
|
||||||
|
|
||||||
client = Client{instanceAPI: stubInstancesClient{CloseErr: someErr}, subnetworkAPI: stubSubnetworksClient{}}
|
client = Client{instanceAPI: stubInstancesClient{CloseErr: someErr}, subnetworkAPI: stubSubnetworksClient{}, forwardingRulesAPI: stubForwardingRulesClient{}}
|
||||||
assert.Error(client.Close())
|
assert.Error(client.Close())
|
||||||
|
|
||||||
client = Client{instanceAPI: stubInstancesClient{}, subnetworkAPI: stubSubnetworksClient{CloseErr: someErr}}
|
client = Client{instanceAPI: stubInstancesClient{}, subnetworkAPI: stubSubnetworksClient{CloseErr: someErr}, forwardingRulesAPI: stubForwardingRulesClient{}}
|
||||||
|
assert.Error(client.Close())
|
||||||
|
|
||||||
|
client = Client{instanceAPI: stubInstancesClient{}, subnetworkAPI: stubSubnetworksClient{}, forwardingRulesAPI: stubForwardingRulesClient{CloseErr: someErr}}
|
||||||
assert.Error(client.Close())
|
assert.Error(client.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,6 +983,40 @@ func (s stubSubnetworksClient) Close() error {
|
|||||||
return s.CloseErr
|
return s.CloseErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type stubForwardingRuleIterator struct {
|
||||||
|
rules []*computepb.ForwardingRule
|
||||||
|
nextErr error
|
||||||
|
|
||||||
|
internalCounter int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *stubForwardingRuleIterator) Next() (*computepb.ForwardingRule, error) {
|
||||||
|
if i.nextErr != nil {
|
||||||
|
return nil, i.nextErr
|
||||||
|
}
|
||||||
|
if i.internalCounter >= len(i.rules) {
|
||||||
|
i.internalCounter = 0
|
||||||
|
return nil, iterator.Done
|
||||||
|
}
|
||||||
|
resp := i.rules[i.internalCounter]
|
||||||
|
i.internalCounter++
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type stubForwardingRulesClient struct {
|
||||||
|
ForwardingRuleIterator ForwardingRuleIterator
|
||||||
|
GetErr error
|
||||||
|
CloseErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stubForwardingRulesClient) List(ctx context.Context, req *computepb.ListForwardingRulesRequest, opts ...gax.CallOption) ForwardingRuleIterator {
|
||||||
|
return s.ForwardingRuleIterator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stubForwardingRulesClient) Close() error {
|
||||||
|
return s.CloseErr
|
||||||
|
}
|
||||||
|
|
||||||
type stubMetadataClient struct {
|
type stubMetadataClient struct {
|
||||||
InstanceValue string
|
InstanceValue string
|
||||||
InstanceErr error
|
InstanceErr error
|
||||||
|
@ -26,6 +26,8 @@ type API interface {
|
|||||||
RetrieveInstanceName() (string, error)
|
RetrieveInstanceName() (string, error)
|
||||||
// RetrieveSubnetworkAliasCIDR retrieves the subnetwork CIDR of the current instance.
|
// RetrieveSubnetworkAliasCIDR retrieves the subnetwork CIDR of the current instance.
|
||||||
RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone, instanceName string) (string, error)
|
RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone, instanceName string) (string, error)
|
||||||
|
// RetrieveLoadBalancerIP retrieves the load balancer IP of the current instance.
|
||||||
|
RetrieveLoadBalancerIP(ctx context.Context, project, zone string) (string, error)
|
||||||
// SetInstanceMetadata sets metadata key: value of the instance specified by project, zone and instanceName.
|
// SetInstanceMetadata sets metadata key: value of the instance specified by project, zone and instanceName.
|
||||||
SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error
|
SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error
|
||||||
// UnsetInstanceMetadata removes a metadata key-value pair of the instance specified by project, zone and instanceName.
|
// UnsetInstanceMetadata removes a metadata key-value pair of the instance specified by project, zone and instanceName.
|
||||||
@ -140,12 +142,20 @@ func (m *Metadata) GetSubnetworkCIDR(ctx context.Context) (string, error) {
|
|||||||
|
|
||||||
// SupportsLoadBalancer returns true if the cloud provider supports load balancers.
|
// SupportsLoadBalancer returns true if the cloud provider supports load balancers.
|
||||||
func (m *Metadata) SupportsLoadBalancer() bool {
|
func (m *Metadata) SupportsLoadBalancer() bool {
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLoadBalancerIP returns the IP of the load balancer.
|
// GetLoadBalancerIP returns the IP of the load balancer.
|
||||||
func (m *Metadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
func (m *Metadata) GetLoadBalancerIP(ctx context.Context) (string, error) {
|
||||||
return "", nil
|
project, err := m.api.RetrieveProjectID()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
zone, err := m.api.RetrieveZone()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return m.api.RetrieveLoadBalancerIP(ctx, project, zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supported is used to determine if metadata API is implemented for this cloud provider.
|
// Supported is used to determine if metadata API is implemented for this cloud provider.
|
||||||
|
@ -368,11 +368,13 @@ type stubGCPClient struct {
|
|||||||
projectID string
|
projectID string
|
||||||
zone string
|
zone string
|
||||||
instanceName string
|
instanceName string
|
||||||
|
loadBalancerIP string
|
||||||
retrieveProjectIDErr error
|
retrieveProjectIDErr error
|
||||||
retrieveZoneErr error
|
retrieveZoneErr error
|
||||||
retrieveInstanceNameErr error
|
retrieveInstanceNameErr error
|
||||||
setInstanceMetadataErr error
|
setInstanceMetadataErr error
|
||||||
unsetInstanceMetadataErr error
|
unsetInstanceMetadataErr error
|
||||||
|
retrieveLoadBalancerErr error
|
||||||
|
|
||||||
instanceMetadataProjects []string
|
instanceMetadataProjects []string
|
||||||
instanceMetadataZones []string
|
instanceMetadataZones []string
|
||||||
@ -410,6 +412,10 @@ func (s *stubGCPClient) RetrieveInstanceName() (string, error) {
|
|||||||
return s.instanceName, s.retrieveInstanceNameErr
|
return s.instanceName, s.retrieveInstanceNameErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stubGCPClient) RetrieveLoadBalancerIP(ctx context.Context, project, zone string) (string, error) {
|
||||||
|
return s.loadBalancerIP, s.retrieveLoadBalancerErr
|
||||||
|
}
|
||||||
|
|
||||||
func (s *stubGCPClient) SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error {
|
func (s *stubGCPClient) SetInstanceMetadata(ctx context.Context, project, zone, instanceName, key, value string) error {
|
||||||
s.instanceMetadataProjects = append(s.instanceMetadataProjects, project)
|
s.instanceMetadataProjects = append(s.instanceMetadataProjects, project)
|
||||||
s.instanceMetadataZones = append(s.instanceMetadataZones, zone)
|
s.instanceMetadataZones = append(s.instanceMetadataZones, zone)
|
||||||
|
@ -43,6 +43,20 @@ func (c *subnetworkClient) Get(ctx context.Context, req *computepb.GetSubnetwork
|
|||||||
return c.SubnetworksClient.Get(ctx, req)
|
return c.SubnetworksClient.Get(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type forwardingRulesClient struct {
|
||||||
|
*compute.ForwardingRulesClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *forwardingRulesClient) Close() error {
|
||||||
|
return c.ForwardingRulesClient.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *forwardingRulesClient) List(ctx context.Context, req *computepb.ListForwardingRulesRequest,
|
||||||
|
opts ...gax.CallOption,
|
||||||
|
) ForwardingRuleIterator {
|
||||||
|
return c.ForwardingRulesClient.List(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
type metadataClient struct{}
|
type metadataClient struct{}
|
||||||
|
|
||||||
func (c *metadataClient) InstanceAttributeValue(attr string) (string, error) {
|
func (c *metadataClient) InstanceAttributeValue(attr string) (string, error) {
|
||||||
|
@ -19,6 +19,9 @@ type ConstellationState struct {
|
|||||||
GCPNetwork string `json:"gcpnetwork,omitempty"`
|
GCPNetwork string `json:"gcpnetwork,omitempty"`
|
||||||
GCPSubnetwork string `json:"gcpsubnetwork,omitempty"`
|
GCPSubnetwork string `json:"gcpsubnetwork,omitempty"`
|
||||||
GCPFirewalls []string `json:"gcpfirewalls,omitempty"`
|
GCPFirewalls []string `json:"gcpfirewalls,omitempty"`
|
||||||
|
GCPBackendService string `json:"gcpbackendservice,omitempty"`
|
||||||
|
GCPHealthCheck string `json:"gcphealthcheck,omitempty"`
|
||||||
|
GCPForwardingRule string `json:"gcpforwardingrule,omitempty"`
|
||||||
GCPProject string `json:"gcpproject,omitempty"`
|
GCPProject string `json:"gcpproject,omitempty"`
|
||||||
GCPZone string `json:"gcpzone,omitempty"`
|
GCPZone string `json:"gcpzone,omitempty"`
|
||||||
GCPRegion string `json:"gcpregion,omitempty"`
|
GCPRegion string `json:"gcpregion,omitempty"`
|
||||||
|
Loading…
Reference in New Issue
Block a user