diff --git a/routines/implementations.go b/routines/implementations.go index 3e73040d..6bf15a09 100644 --- a/routines/implementations.go +++ b/routines/implementations.go @@ -2,15 +2,16 @@ package routines import ( "fmt" - "github.com/chelnak/ysmrr" - xfs "github.com/saitho/golang-extended-fs/v2" - logger "github.com/sirupsen/logrus" - "gopkg.in/yaml.v3" "path" "strconv" "strings" "time" + "github.com/chelnak/ysmrr" + xfs "github.com/saitho/golang-extended-fs/v2" + logger "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + "github.com/getstackhead/stackhead/project" "github.com/getstackhead/stackhead/system" ) @@ -111,24 +112,8 @@ var RollbackResources = Task{ } var errors []error for _, resourceGroup := range resourceRollbackOrder { - if resourceGroup.RollbackResourceFunc != nil { - if err := resourceGroup.RollbackResourceFunc(); err != nil { - errors = append(errors, fmt.Errorf("Unable to completely rollback resources: %s", err)) - } - } - for _, resource := range resourceGroup.Resources { - spinner := r.TaskRunner.GetNewSubtaskSpinner(resource.ToString(true)) - matched, err := system.RollbackResourceOperation(resource, false) - if !matched || err == nil { - if spinner != nil { - spinner.Complete() - } - } else if err != nil { - errors = append(errors, fmt.Errorf("Rollback error: %s", err)) - if spinner != nil { - spinner.Error() - } - } + if _, err := processResourceGroup(r.TaskRunner, resourceGroup, true, false); err != nil { + errors = append(errors, fmt.Errorf("Rollback error: %s", err)) } } @@ -146,48 +131,73 @@ var RollbackResources = Task{ }, } +// return: bool: whether to consider resource group for requiring rollback ; error +func processResourceGroup(taskRunner *TaskRunner, resourceGroup system.ResourceGroup, isRollbackMode bool, ignoreBackup bool) (bool, error) { + var uncompletedSpinners []*ysmrr.Spinner + var errors []error + + // ROLLBACK mode + if isRollbackMode && resourceGroup.RollbackResourceFunc != nil { + if err := resourceGroup.RollbackResourceFunc(); err != nil { + errors = append(errors, fmt.Errorf("Unable to completely rollback resources: %s", err)) + } + } + + for _, resource := range resourceGroup.Resources { + spinner := taskRunner.GetNewSubtaskSpinner(resource.ToString(isRollbackMode)) + var err error + var processed bool + if isRollbackMode { + processed, err = system.RollbackResourceOperation(resource, ignoreBackup) + } else { + processed, err = system.ApplyResourceOperation(resource, ignoreBackup) + } + if err != nil { + if spinner != nil { + spinner.UpdateMessage(err.Error()) + spinner.Error() + } + return false, err + } + + if spinner != nil { + if processed { + spinner.Complete() + } else { + // uncompleted spinners are resolved when resource group finishes + uncompletedSpinners = append(uncompletedSpinners, spinner) + } + } + } + + // APPLY mode + if !isRollbackMode && resourceGroup.ApplyResourceFunc != nil { + if err := resourceGroup.ApplyResourceFunc(); err != nil { + for _, spinner := range uncompletedSpinners { + spinner.Error() + } + return true, err + } + } + for _, spinner := range uncompletedSpinners { + spinner.Complete() + } + return true, nil +} + var CreateResources = Task{ Name: "Creating resources", Run: func(r *Task) error { var errors []string - var uncompletedSpinners []*ysmrr.Spinner - for _, resourceGroup := range system.Context.CurrentDeployment.ResourceGroups { - for _, resource := range resourceGroup.Resources { - spinner := r.TaskRunner.GetNewSubtaskSpinner(resource.ToString(false)) - processed, err := system.ApplyResourceOperation(resource, false) - if err != nil { - rollback = true - if spinner != nil { - spinner.UpdateMessage(err.Error()) - spinner.Error() - } - return err - } - - if spinner != nil { - if processed { - spinner.Complete() - } else { - // uncompleted spinners are resolved when resource group finishes - uncompletedSpinners = append(uncompletedSpinners, spinner) - } - } - } - resourceRollbackOrder = append([]system.ResourceGroup{resourceGroup}, resourceRollbackOrder...) - if resourceGroup.ApplyResourceFunc != nil { - if err := resourceGroup.ApplyResourceFunc(); err != nil { - for _, spinner := range uncompletedSpinners { - spinner.Error() - } - rollback = true - errors = append(errors, fmt.Sprintf("Unable to complete resource creation: %s", err)) - } + considerForRollback, err := processResourceGroup(r.TaskRunner, resourceGroup, false, false) + if considerForRollback { + resourceRollbackOrder = append([]system.ResourceGroup{resourceGroup}, resourceRollbackOrder...) } - if !rollback { - for _, spinner := range uncompletedSpinners { - spinner.Complete() - } + if err != nil { + rollback = true + errors = append(errors, err.Error()) + break } } if !rollback { @@ -215,36 +225,20 @@ var RemoveResources = func(latestDeployment *system.Deployment) Task { return Task{ Name: "Removing project resources", Run: func(r *Task) error { - var uncompletedSpinners []*ysmrr.Spinner - reverse(latestDeployment.ResourceGroups) for _, group := range latestDeployment.ResourceGroups { - reverse(group.Resources) + var filteredResources []system.Resource for _, resource := range group.Resources { if resource.ExternalResource { resource.Operation = system.OperationDelete - spinner := r.TaskRunner.GetNewSubtaskSpinner(resource.ToString(false)) - if processed, err := system.PerformOperation(resource, true); err != nil { - if err != nil { - if spinner != nil { - spinner.UpdateMessage(err.Error()) - spinner.Error() - } - return err - } - if spinner != nil { - if processed { - spinner.Complete() - } else { - // uncompleted spinners are resolved when resource group finishes - uncompletedSpinners = append(uncompletedSpinners, spinner) - } - } - } + filteredResources = append(filteredResources, resource) } } - for _, spinner := range uncompletedSpinners { - spinner.Complete() + reverse(filteredResources) + group.Resources = filteredResources + + if _, err := processResourceGroup(r.TaskRunner, group, false, true); err != nil { + return err } } return nil