mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
Check for 404 errors in GCP termination
This commit is contained in:
parent
9f599c3993
commit
c954ec089f
@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
compute "cloud.google.com/go/compute/apiv1"
|
compute "cloud.google.com/go/compute/apiv1"
|
||||||
admin "cloud.google.com/go/iam/admin/apiv1"
|
admin "cloud.google.com/go/iam/admin/apiv1"
|
||||||
@ -15,6 +17,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
"go.uber.org/multierr"
|
"go.uber.org/multierr"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is a client for the Google Compute Engine.
|
// Client is a client for the Google Compute Engine.
|
||||||
@ -318,3 +321,11 @@ func closeAll(closers []closer) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isNotFoundError(err error) bool {
|
||||||
|
var gAPIErr *googleapi.Error
|
||||||
|
if !errors.As(err, &gAPIErr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return gAPIErr.Code == http.StatusNotFound
|
||||||
|
}
|
||||||
|
@ -131,20 +131,24 @@ func (c *Client) TerminateInstances(ctx context.Context) error {
|
|||||||
ops := []Operation{}
|
ops := []Operation{}
|
||||||
if c.workerInstanceGroup != "" {
|
if c.workerInstanceGroup != "" {
|
||||||
op, err := c.deleteInstanceGroupManager(ctx, c.workerInstanceGroup)
|
op, err := c.deleteInstanceGroupManager(ctx, c.workerInstanceGroup)
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return fmt.Errorf("deleting instanceGroupManager '%s': %w", c.workerInstanceGroup, err)
|
return fmt.Errorf("deleting instanceGroupManager '%s': %w", c.workerInstanceGroup, err)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
|
}
|
||||||
c.workerInstanceGroup = ""
|
c.workerInstanceGroup = ""
|
||||||
c.workers = make(cloudtypes.Instances)
|
c.workers = make(cloudtypes.Instances)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.controlPlaneInstanceGroup != "" {
|
if c.controlPlaneInstanceGroup != "" {
|
||||||
op, err := c.deleteInstanceGroupManager(ctx, c.controlPlaneInstanceGroup)
|
op, err := c.deleteInstanceGroupManager(ctx, c.controlPlaneInstanceGroup)
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return fmt.Errorf("deleting instanceGroupManager '%s': %w", c.controlPlaneInstanceGroup, err)
|
return fmt.Errorf("deleting instanceGroupManager '%s': %w", c.controlPlaneInstanceGroup, err)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
|
}
|
||||||
c.controlPlaneInstanceGroup = ""
|
c.controlPlaneInstanceGroup = ""
|
||||||
c.controlPlanes = make(cloudtypes.Instances)
|
c.controlPlanes = make(cloudtypes.Instances)
|
||||||
}
|
}
|
||||||
@ -155,18 +159,22 @@ func (c *Client) TerminateInstances(ctx context.Context) error {
|
|||||||
|
|
||||||
if c.workerTemplate != "" {
|
if c.workerTemplate != "" {
|
||||||
op, err := c.deleteInstanceTemplate(ctx, c.workerTemplate)
|
op, err := c.deleteInstanceTemplate(ctx, c.workerTemplate)
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return fmt.Errorf("deleting instanceTemplate: %w", err)
|
return fmt.Errorf("deleting instanceTemplate: %w", err)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
|
}
|
||||||
c.workerTemplate = ""
|
c.workerTemplate = ""
|
||||||
}
|
}
|
||||||
if c.controlPlaneTemplate != "" {
|
if c.controlPlaneTemplate != "" {
|
||||||
op, err := c.deleteInstanceTemplate(ctx, c.controlPlaneTemplate)
|
op, err := c.deleteInstanceTemplate(ctx, c.controlPlaneTemplate)
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return fmt.Errorf("deleting instanceTemplate: %w", err)
|
return fmt.Errorf("deleting instanceTemplate: %w", err)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
|
}
|
||||||
c.controlPlaneTemplate = ""
|
c.controlPlaneTemplate = ""
|
||||||
}
|
}
|
||||||
return c.waitForOperations(ctx, ops)
|
return c.waitForOperations(ctx, ops)
|
||||||
|
@ -3,10 +3,12 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"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/api/googleapi"
|
||||||
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"
|
||||||
)
|
)
|
||||||
@ -180,6 +182,8 @@ func TestCreateInstances(t *testing.T) {
|
|||||||
|
|
||||||
func TestTerminateInstances(t *testing.T) {
|
func TestTerminateInstances(t *testing.T) {
|
||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
|
notFoundErr := &googleapi.Error{Code: http.StatusNotFound}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
operationZoneAPI operationZoneAPI
|
operationZoneAPI operationZoneAPI
|
||||||
operationGlobalAPI operationGlobalAPI
|
operationGlobalAPI operationGlobalAPI
|
||||||
@ -202,6 +206,18 @@ func TestTerminateInstances(t *testing.T) {
|
|||||||
instanceGroupManagersAPI: stubInstanceGroupManagersAPI{},
|
instanceGroupManagersAPI: stubInstanceGroupManagersAPI{},
|
||||||
missingWorkerInstanceGroup: true,
|
missingWorkerInstanceGroup: true,
|
||||||
},
|
},
|
||||||
|
"instances not found": {
|
||||||
|
operationZoneAPI: stubOperationZoneAPI{},
|
||||||
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
instanceTemplateAPI: stubInstanceTemplateAPI{},
|
||||||
|
instanceGroupManagersAPI: stubInstanceGroupManagersAPI{deleteErr: notFoundErr},
|
||||||
|
},
|
||||||
|
"templates not found": {
|
||||||
|
operationZoneAPI: stubOperationZoneAPI{},
|
||||||
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
instanceTemplateAPI: stubInstanceTemplateAPI{deleteErr: notFoundErr},
|
||||||
|
instanceGroupManagersAPI: stubInstanceGroupManagersAPI{},
|
||||||
|
},
|
||||||
"fail delete instanceGroupManager": {
|
"fail delete instanceGroupManager": {
|
||||||
operationZoneAPI: stubOperationZoneAPI{},
|
operationZoneAPI: stubOperationZoneAPI{},
|
||||||
operationGlobalAPI: stubOperationGlobalAPI{},
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
@ -65,6 +65,9 @@ func (c *Client) TerminateFirewall(ctx context.Context) error {
|
|||||||
Project: c.project,
|
Project: c.project,
|
||||||
}
|
}
|
||||||
resp, err := c.firewallsAPI.Delete(ctx, req)
|
resp, err := c.firewallsAPI.Delete(ctx, req)
|
||||||
|
if isNotFoundError(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -130,28 +133,40 @@ func (c *Client) TerminateVPCs(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var op Operation
|
if err := c.terminateVPC(ctx); err != nil {
|
||||||
var err error
|
|
||||||
if c.network != "" {
|
|
||||||
op, err = c.terminateVPC(ctx, c.network)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.network = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.waitForOperations(ctx, []Operation{op})
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminateVPC terminates a VPC network.
|
// terminateVPC terminates a VPC network.
|
||||||
//
|
//
|
||||||
// If the network has firewall rules, these must be terminated first.
|
// If the network has firewall rules, these must be terminated first.
|
||||||
func (c *Client) terminateVPC(ctx context.Context, network string) (Operation, error) {
|
func (c *Client) terminateVPC(ctx context.Context) error {
|
||||||
|
if c.network == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
req := &computepb.DeleteNetworkRequest{
|
req := &computepb.DeleteNetworkRequest{
|
||||||
Project: c.project,
|
Project: c.project,
|
||||||
Network: network,
|
Network: c.network,
|
||||||
}
|
}
|
||||||
return c.networksAPI.Delete(ctx, req)
|
op, err := c.networksAPI.Delete(ctx, req)
|
||||||
|
if err != nil && !isNotFoundError(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isNotFoundError(err) {
|
||||||
|
c.network = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.waitForOperations(ctx, []Operation{op}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.network = ""
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) createSubnets(ctx context.Context) error {
|
func (c *Client) createSubnets(ctx context.Context) error {
|
||||||
@ -189,16 +204,27 @@ func (c *Client) terminateSubnet(ctx context.Context) error {
|
|||||||
if c.subnetwork == "" {
|
if c.subnetwork == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &computepb.DeleteSubnetworkRequest{
|
req := &computepb.DeleteSubnetworkRequest{
|
||||||
Project: c.project,
|
Project: c.project,
|
||||||
Region: c.region,
|
Region: c.region,
|
||||||
Subnetwork: c.subnetwork,
|
Subnetwork: c.subnetwork,
|
||||||
}
|
}
|
||||||
op, err := c.subnetworksAPI.Delete(ctx, req)
|
op, err := c.subnetworksAPI.Delete(ctx, req)
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.waitForOperations(ctx, []Operation{op})
|
if isNotFoundError(err) {
|
||||||
|
c.subnetwork = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.waitForOperations(ctx, []Operation{op}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.subnetwork = ""
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateLoadBalancer creates a load balancer.
|
// CreateLoadBalancer creates a load balancer.
|
||||||
@ -305,33 +331,43 @@ func (c *Client) TerminateLoadBalancer(ctx context.Context) error {
|
|||||||
Region: c.region,
|
Region: c.region,
|
||||||
ForwardingRule: c.forwardingRule,
|
ForwardingRule: c.forwardingRule,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
|
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp, err = c.backendServicesAPI.Delete(ctx, &computepb.DeleteRegionBackendServiceRequest{
|
resp, err = c.backendServicesAPI.Delete(ctx, &computepb.DeleteRegionBackendServiceRequest{
|
||||||
Project: c.project,
|
Project: c.project,
|
||||||
Region: c.region,
|
Region: c.region,
|
||||||
BackendService: c.backendService,
|
BackendService: c.backendService,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
|
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp, err = c.healthChecksAPI.Delete(ctx, &computepb.DeleteRegionHealthCheckRequest{
|
resp, err = c.healthChecksAPI.Delete(ctx, &computepb.DeleteRegionHealthCheckRequest{
|
||||||
Project: c.project,
|
Project: c.project,
|
||||||
Region: c.region,
|
Region: c.region,
|
||||||
HealthCheck: c.healthCheck,
|
HealthCheck: c.healthCheck,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && !isNotFoundError(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.waitForOperations(ctx, []Operation{resp})
|
if err == nil {
|
||||||
|
if err := c.waitForOperations(ctx, []Operation{resp}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,12 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"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/api/googleapi"
|
||||||
"google.golang.org/genproto/googleapis/cloud/compute/v1"
|
"google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
@ -87,6 +89,8 @@ func TestCreateVPCs(t *testing.T) {
|
|||||||
|
|
||||||
func TestTerminateVPCs(t *testing.T) {
|
func TestTerminateVPCs(t *testing.T) {
|
||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
|
notFoundErr := &googleapi.Error{Code: http.StatusNotFound}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
operationGlobalAPI operationGlobalAPI
|
operationGlobalAPI operationGlobalAPI
|
||||||
operationRegionAPI operationRegionAPI
|
operationRegionAPI operationRegionAPI
|
||||||
@ -94,6 +98,7 @@ func TestTerminateVPCs(t *testing.T) {
|
|||||||
subnetworksAPI subnetworksAPI
|
subnetworksAPI subnetworksAPI
|
||||||
firewalls []string
|
firewalls []string
|
||||||
subnetwork string
|
subnetwork string
|
||||||
|
network string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"successful terminate": {
|
"successful terminate": {
|
||||||
@ -102,6 +107,7 @@ func TestTerminateVPCs(t *testing.T) {
|
|||||||
networksAPI: stubNetworksAPI{},
|
networksAPI: stubNetworksAPI{},
|
||||||
subnetworksAPI: stubSubnetworksAPI{},
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
subnetwork: "subnetwork-id-1",
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
},
|
},
|
||||||
"subnetwork empty": {
|
"subnetwork empty": {
|
||||||
operationGlobalAPI: stubOperationGlobalAPI{},
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
@ -109,30 +115,58 @@ func TestTerminateVPCs(t *testing.T) {
|
|||||||
networksAPI: stubNetworksAPI{},
|
networksAPI: stubNetworksAPI{},
|
||||||
subnetworksAPI: stubSubnetworksAPI{},
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
subnetwork: "",
|
subnetwork: "",
|
||||||
|
network: "network-id-1",
|
||||||
|
},
|
||||||
|
"network empty": {
|
||||||
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
|
networksAPI: stubNetworksAPI{},
|
||||||
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "",
|
||||||
|
},
|
||||||
|
"subnetwork not found": {
|
||||||
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
|
networksAPI: stubNetworksAPI{},
|
||||||
|
subnetworksAPI: stubSubnetworksAPI{deleteErr: notFoundErr},
|
||||||
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
|
},
|
||||||
|
"network not found": {
|
||||||
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
|
networksAPI: stubNetworksAPI{deleteErr: notFoundErr},
|
||||||
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
},
|
},
|
||||||
"failed wait global op": {
|
"failed wait global op": {
|
||||||
operationGlobalAPI: stubOperationGlobalAPI{waitErr: someErr},
|
operationGlobalAPI: stubOperationGlobalAPI{waitErr: someErr},
|
||||||
operationRegionAPI: stubOperationRegionAPI{},
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
networksAPI: stubNetworksAPI{},
|
networksAPI: stubNetworksAPI{},
|
||||||
subnetworksAPI: stubSubnetworksAPI{},
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
wantErr: true,
|
|
||||||
subnetwork: "subnetwork-id-1",
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"failed delete networks": {
|
"failed delete networks": {
|
||||||
operationGlobalAPI: stubOperationGlobalAPI{},
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
operationRegionAPI: stubOperationRegionAPI{},
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
networksAPI: stubNetworksAPI{deleteErr: someErr},
|
networksAPI: stubNetworksAPI{deleteErr: someErr},
|
||||||
subnetworksAPI: stubSubnetworksAPI{},
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
wantErr: true,
|
|
||||||
subnetwork: "subnetwork-id-1",
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"failed delete subnetworks": {
|
"failed delete subnetworks": {
|
||||||
operationGlobalAPI: stubOperationGlobalAPI{},
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
operationRegionAPI: stubOperationRegionAPI{},
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
networksAPI: stubNetworksAPI{},
|
networksAPI: stubNetworksAPI{},
|
||||||
subnetworksAPI: stubSubnetworksAPI{deleteErr: someErr},
|
subnetworksAPI: stubSubnetworksAPI{deleteErr: someErr},
|
||||||
wantErr: true,
|
|
||||||
subnetwork: "subnetwork-id-1",
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"must delete firewalls first": {
|
"must delete firewalls first": {
|
||||||
firewalls: []string{"firewall-1", "firewall-2"},
|
firewalls: []string{"firewall-1", "firewall-2"},
|
||||||
@ -140,8 +174,9 @@ func TestTerminateVPCs(t *testing.T) {
|
|||||||
operationGlobalAPI: stubOperationGlobalAPI{},
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
networksAPI: stubNetworksAPI{},
|
networksAPI: stubNetworksAPI{},
|
||||||
subnetworksAPI: stubSubnetworksAPI{},
|
subnetworksAPI: stubSubnetworksAPI{},
|
||||||
wantErr: true,
|
|
||||||
subnetwork: "subnetwork-id-1",
|
subnetwork: "subnetwork-id-1",
|
||||||
|
network: "network-id-1",
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +195,7 @@ func TestTerminateVPCs(t *testing.T) {
|
|||||||
networksAPI: tc.networksAPI,
|
networksAPI: tc.networksAPI,
|
||||||
subnetworksAPI: tc.subnetworksAPI,
|
subnetworksAPI: tc.subnetworksAPI,
|
||||||
firewalls: tc.firewalls,
|
firewalls: tc.firewalls,
|
||||||
network: "network-id-1",
|
network: tc.network,
|
||||||
subnetwork: tc.subnetwork,
|
subnetwork: tc.subnetwork,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +204,7 @@ func TestTerminateVPCs(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
assert.NoError(client.TerminateVPCs(ctx))
|
assert.NoError(client.TerminateVPCs(ctx))
|
||||||
assert.Empty(client.network)
|
assert.Empty(client.network)
|
||||||
|
assert.Empty(client.subnetwork)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -254,6 +290,7 @@ func TestCreateFirewall(t *testing.T) {
|
|||||||
|
|
||||||
func TestTerminateFirewall(t *testing.T) {
|
func TestTerminateFirewall(t *testing.T) {
|
||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
|
notFoundErr := &googleapi.Error{Code: http.StatusNotFound}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
operationGlobalAPI operationGlobalAPI
|
operationGlobalAPI operationGlobalAPI
|
||||||
@ -271,6 +308,11 @@ func TestTerminateFirewall(t *testing.T) {
|
|||||||
firewallsAPI: stubFirewallsAPI{},
|
firewallsAPI: stubFirewallsAPI{},
|
||||||
firewalls: []string{},
|
firewalls: []string{},
|
||||||
},
|
},
|
||||||
|
"successful terminate when firewall not found": {
|
||||||
|
operationGlobalAPI: stubOperationGlobalAPI{},
|
||||||
|
firewallsAPI: stubFirewallsAPI{deleteErr: notFoundErr},
|
||||||
|
firewalls: []string{"firewall-1", "firewall-2"},
|
||||||
|
},
|
||||||
"failed to wait on global operation": {
|
"failed to wait on global operation": {
|
||||||
operationGlobalAPI: stubOperationGlobalAPI{waitErr: someErr},
|
operationGlobalAPI: stubOperationGlobalAPI{waitErr: someErr},
|
||||||
firewallsAPI: stubFirewallsAPI{},
|
firewallsAPI: stubFirewallsAPI{},
|
||||||
@ -399,6 +441,8 @@ func TestCreateLoadBalancer(t *testing.T) {
|
|||||||
|
|
||||||
func TestTerminateLoadBalancer(t *testing.T) {
|
func TestTerminateLoadBalancer(t *testing.T) {
|
||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
|
notFoundErr := &googleapi.Error{Code: http.StatusNotFound}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
operationRegionAPI operationRegionAPI
|
operationRegionAPI operationRegionAPI
|
||||||
healthChecksAPI healthChecksAPI
|
healthChecksAPI healthChecksAPI
|
||||||
@ -412,6 +456,24 @@ func TestTerminateLoadBalancer(t *testing.T) {
|
|||||||
forwardingRulesAPI: stubForwardingRulesAPI{},
|
forwardingRulesAPI: stubForwardingRulesAPI{},
|
||||||
operationRegionAPI: stubOperationRegionAPI{},
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
},
|
},
|
||||||
|
"successful terminate when health check not found": {
|
||||||
|
healthChecksAPI: stubHealthChecksAPI{deleteErr: notFoundErr},
|
||||||
|
backendServicesAPI: stubBackendServicesAPI{},
|
||||||
|
forwardingRulesAPI: stubForwardingRulesAPI{},
|
||||||
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
|
},
|
||||||
|
"successful terminate when backend service not found": {
|
||||||
|
healthChecksAPI: stubHealthChecksAPI{},
|
||||||
|
backendServicesAPI: stubBackendServicesAPI{deleteErr: notFoundErr},
|
||||||
|
forwardingRulesAPI: stubForwardingRulesAPI{},
|
||||||
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
|
},
|
||||||
|
"successful terminate when forwarding rule not found": {
|
||||||
|
healthChecksAPI: stubHealthChecksAPI{},
|
||||||
|
backendServicesAPI: stubBackendServicesAPI{},
|
||||||
|
forwardingRulesAPI: stubForwardingRulesAPI{deleteErr: notFoundErr},
|
||||||
|
operationRegionAPI: stubOperationRegionAPI{},
|
||||||
|
},
|
||||||
"TerminateLoadBalancer fails when deleting health check": {
|
"TerminateLoadBalancer fails when deleting health check": {
|
||||||
healthChecksAPI: stubHealthChecksAPI{deleteErr: someErr},
|
healthChecksAPI: stubHealthChecksAPI{deleteErr: someErr},
|
||||||
backendServicesAPI: stubBackendServicesAPI{},
|
backendServicesAPI: stubBackendServicesAPI{},
|
||||||
|
@ -38,15 +38,18 @@ func (c *Client) CreateServiceAccount(ctx context.Context, input ServiceAccountI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TerminateServiceAccount(ctx context.Context) error {
|
func (c *Client) TerminateServiceAccount(ctx context.Context) error {
|
||||||
if c.serviceAccount != "" {
|
if c.serviceAccount == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
req := &adminpb.DeleteServiceAccountRequest{
|
req := &adminpb.DeleteServiceAccountRequest{
|
||||||
Name: "projects/-/serviceAccounts/" + c.serviceAccount,
|
Name: "projects/-/serviceAccounts/" + c.serviceAccount,
|
||||||
}
|
}
|
||||||
if err := c.iamAPI.DeleteServiceAccount(ctx, req); err != nil {
|
if err := c.iamAPI.DeleteServiceAccount(ctx, req); err != nil && !isNotFoundError(err) {
|
||||||
return fmt.Errorf("deleting service account: %w", err)
|
return fmt.Errorf("deleting service account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.serviceAccount = ""
|
c.serviceAccount = ""
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user