Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make delete async #24

Merged
merged 3 commits into from
May 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 4 additions & 34 deletions pkg/cloud/gcp/actuators/machine/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@ import (
apicorev1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
userDataSecretKey = "userData"
operationTimeOut = 180 * time.Second
operationRetryWait = 5 * time.Second
requeueAfterSeconds = 20
)

Expand Down Expand Up @@ -212,29 +209,6 @@ func (r *Reconciler) getCustomUserData() (string, error) {
return base64.StdEncoding.EncodeToString(data), nil
}

func (r *Reconciler) waitUntilOperationCompleted(zone, operationName string) (*compute.Operation, error) {
var op *compute.Operation
var err error
return op, wait.Poll(operationRetryWait, operationTimeOut, func() (bool, error) {
op, err = r.computeService.ZoneOperationsGet(r.projectID, zone, operationName)
if err != nil {
return false, err
}
klog.V(3).Infof("Waiting for %q operation to be completed... (status: %s)", op.OperationType, op.Status)
if op.Status == "DONE" {
if op.Error == nil {
return true, nil
}
var err []error
for _, opErr := range op.Error.Errors {
err = append(err, fmt.Errorf("%s", *opErr))
}
return false, fmt.Errorf("the following errors occurred: %+v", err)
}
return false, nil
})
}

func validateMachine(machine machinev1.Machine, providerSpec v1beta1.GCPMachineProviderSpec) error {
// TODO (alberto): First validation should happen via webhook before the object is persisted.
// This is a complementary validation to fail early in case of lacking proper webhook validation.
Expand All @@ -257,7 +231,7 @@ func (r *Reconciler) exists() (bool, error) {
if err == nil {
switch instance.Status {
case "TERMINATED":
klog.Infof("Machine %q is considered as non existent as its status is %q", instance.Status)
klog.Infof("Machine %q is considered as non existent as its status is %q", r.machine.Name, instance.Status)
return false, nil
default:
klog.Infof("Machine %q already exists", r.machine.Name)
Expand All @@ -281,15 +255,11 @@ func (r *Reconciler) delete() error {
klog.Infof("Machine %v not found during delete, skipping", r.machine.Name)
return nil
}
zone := r.providerSpec.Zone
operation, err := r.computeService.InstancesDelete(r.projectID, zone, r.machine.Name)
if err != nil {
if _, err = r.computeService.InstancesDelete(string(r.machine.UID), r.projectID, r.providerSpec.Zone, r.machine.Name); err != nil {
return fmt.Errorf("failed to delete instance via compute service: %v", err)
}
if op, err := r.waitUntilOperationCompleted(zone, operation.Name); err != nil {
return fmt.Errorf("failed to wait for delete operation via compute service. Operation status: %v. Error: %v", op, err)
}
return nil
klog.Infof("machine %q status is exists, requeuing...", r.machine.Name)
return &clustererror.RequeueAfterError{RequeueAfter: requeueAfterSeconds * time.Second}
}

func (r *Reconciler) validateZone() error {
Expand Down
5 changes: 4 additions & 1 deletion pkg/cloud/gcp/actuators/machine/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
gcpv1beta1 "github.com/openshift/cluster-api-provider-gcp/pkg/apis/gcpprovider/v1beta1"
computeservice "github.com/openshift/cluster-api-provider-gcp/pkg/cloud/gcp/actuators/services/compute"
machinev1beta1 "github.com/openshift/cluster-api/pkg/apis/machine/v1beta1"
controllerError "github.com/openshift/cluster-api/pkg/controller/error"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
controllerfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
Expand Down Expand Up @@ -137,6 +138,8 @@ func TestDelete(t *testing.T) {
}
reconciler := newReconciler(&machineScope)
if err := reconciler.delete(); err != nil {
t.Errorf("reconciler was not expected to return error: %v", err)
if _, ok := err.(*controllerError.RequeueAfterError); !ok {
t.Errorf("reconciler was not expected to return error: %v", err)
}
}
}
9 changes: 5 additions & 4 deletions pkg/cloud/gcp/actuators/services/compute/computeservice.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package computeservice

import (
"google.golang.org/api/compute/v1"
"net/http"

"google.golang.org/api/compute/v1"
)

// GCPComputeService is a pass through wrapper for google.golang.org/api/compute/v1/compute
// to enable tests to mock this struct and control behavior.
type GCPComputeService interface {
InstancesDelete(project string, zone string, instance string) (*compute.Operation, error)
InstancesDelete(requestId string, project string, zone string, instance string) (*compute.Operation, error)
InstancesInsert(project string, zone string, instance *compute.Instance) (*compute.Operation, error)
InstancesGet(project string, zone string, instance string) (*compute.Instance, error)
ZonesGet(project string, zone string) (*compute.Zone, error)
Expand Down Expand Up @@ -44,8 +45,8 @@ func (c *computeService) InstancesGet(project string, zone string, instance stri
return c.service.Instances.Get(project, zone, instance).Do()
}

func (c *computeService) InstancesDelete(project string, zone string, instance string) (*compute.Operation, error) {
return c.service.Instances.Delete(project, zone, instance).Do()
func (c *computeService) InstancesDelete(requestId string, project string, zone string, instance string) (*compute.Operation, error) {
return c.service.Instances.Delete(project, zone, instance).RequestId(requestId).Do()
}

func (c *computeService) ZonesGet(project string, zone string) (*compute.Zone, error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (c *GCPComputeServiceMock) InstancesInsert(project string, zone string, ins
return c.mockInstancesInsert(project, zone, instance)
}

func (c *GCPComputeServiceMock) InstancesDelete(project string, zone string, instance string) (*compute.Operation, error) {
func (c *GCPComputeServiceMock) InstancesDelete(requestId string, project string, zone string, instance string) (*compute.Operation, error) {
return &compute.Operation{
Status: "DONE",
}, nil
Expand Down