diff --git a/installer/cmd/tectonic/main.go b/installer/cmd/tectonic/main.go index a0f7a0a4d86..85eca882bc3 100644 --- a/installer/cmd/tectonic/main.go +++ b/installer/cmd/tectonic/main.go @@ -16,8 +16,9 @@ var ( clusterInstallCommand = kingpin.Command("install", "Create a new Tectonic cluster") clusterInstallDirFlag = clusterInstallCommand.Flag("dir", "Cluster directory").Default(".").ExistingDir() - clusterDestroyCommand = kingpin.Command("destroy", "Destroy an existing Tectonic cluster") - clusterDestroyDirFlag = clusterDestroyCommand.Flag("dir", "Cluster directory").Default(".").ExistingDir() + clusterDestroyCommand = kingpin.Command("destroy", "Destroy an existing Tectonic cluster") + clusterDestroyDirFlag = clusterDestroyCommand.Flag("dir", "Cluster directory").Default(".").ExistingDir() + clusterDestroyContOnErr = clusterDestroyCommand.Flag("continue-on-error", "Log errors, but attempt to continue cleaning up the cluster. THIS MAY LEAK RESOURCES, because you may not have enough state left after a partial removal to be able to perform a second destroy.").Default("false").Bool() convertCommand = kingpin.Command("convert", "Convert a tfvars.json to a Tectonic config.yaml") convertConfigFlag = convertCommand.Flag("config", "tfvars.json file").Required().ExistingFile() @@ -34,7 +35,7 @@ func main() { case clusterInstallCommand.FullCommand(): w = workflow.InstallWorkflow(*clusterInstallDirFlag) case clusterDestroyCommand.FullCommand(): - w = workflow.DestroyWorkflow(*clusterDestroyDirFlag) + w = workflow.DestroyWorkflow(*clusterDestroyDirFlag, *clusterDestroyContOnErr) case convertCommand.FullCommand(): w = workflow.ConvertWorkflow(*convertConfigFlag) } diff --git a/installer/pkg/workflow/destroy.go b/installer/pkg/workflow/destroy.go index c4193e542e6..a77b23653ba 100644 --- a/installer/pkg/workflow/destroy.go +++ b/installer/pkg/workflow/destroy.go @@ -22,9 +22,12 @@ const ( // DestroyWorkflow creates new instances of the 'destroy' workflow, // responsible for running the actions required to remove resources // of an existing cluster and clean up any remaining artefacts. -func DestroyWorkflow(clusterDir string) Workflow { +func DestroyWorkflow(clusterDir string, contOnErr bool) Workflow { return Workflow{ - metadata: metadata{clusterDir: clusterDir}, + metadata: metadata{ + clusterDir: clusterDir, + contOnErr: contOnErr, + }, steps: []step{ readClusterConfigStep, generateTerraformVariablesStep, diff --git a/installer/pkg/workflow/workflow.go b/installer/pkg/workflow/workflow.go index 508ebf43d9e..fe0749606b5 100644 --- a/installer/pkg/workflow/workflow.go +++ b/installer/pkg/workflow/workflow.go @@ -1,6 +1,9 @@ package workflow -import "github.com/openshift/installer/installer/pkg/config" +import ( + log "github.com/Sirupsen/logrus" + "github.com/openshift/installer/installer/pkg/config" +) // metadata is the state store of the current workflow execution. // It is meant to carry state for one step to another. @@ -12,6 +15,7 @@ type metadata struct { cluster config.Cluster configFilePath string clusterDir string + contOnErr bool } // step is the entrypoint of a workflow step implementation. @@ -28,11 +32,18 @@ type Workflow struct { // Execute runs all steps in order. func (w Workflow) Execute() error { + var firstError error for _, step := range w.steps { if err := step(&w.metadata); err != nil { - return err + if !w.metadata.contOnErr { + return err + } + if firstError == nil { + firstError = err + } + log.Warn(err) } } - return nil + return firstError }