func (c *BuildCommand) Execute(args []string) error { sysConfig := BuiltinConfig sysConfig.Discover() config, err := padstone.LoadConfig(c.Args.ConfigDir) if err != nil { return err } storage := &tfmodcfg.FolderStorage{ StorageDir: ".padstone", } // The state file must not already exist, since we don't to // accidentally clobber the record of resources created in an // earlier build. _, err = os.Lstat(c.Args.StateFile) if err == nil { return fmt.Errorf("state file %s already exists; specify a different name or destroy it with 'padstone destroy' before generating a new set of resources", c.Args.StateFile) } state := terraform.NewState() uiHook := &UIHook{ ui: c.ui, verbose: c.Verbose, } stateHook := &StateHook{ OutputFilename: c.Args.StateFile, } variables, err := decodeKVSpecs(c.Args.VarSpecs) if err != nil { return err } ctx := &padstone.Context{ Config: config, State: state, Providers: sysConfig.ProviderFactories(), Provisioners: sysConfig.ProvisionerFactories(), Variables: variables, Hooks: []terraform.Hook{stateHook, uiHook}, UIInput: c.ui, ModuleStorage: storage, } warns, errs := ctx.Validate() for _, warning := range warns { c.ui.Warn(warning) } if len(errs) > 0 { for _, err := range errs { c.ui.Error(err.Error()) } return fmt.Errorf("aborted due to configuration errors.") } err = ctx.Build() if err != nil { return err } c.ui.Info("--- Build succeeded! Now destroying temporary resources... ---") err = ctx.CleanUp() if err != nil { return err } _, err = stateHook.PostStateUpdate(ctx.ResultState) if err != nil { return err } outputs := ctx.ResultState.Modules[0].Outputs if len(outputs) > 0 { c.ui.Output("\nOutputs:") for k, v := range outputs { c.ui.Output(fmt.Sprintf("- %v = %v", k, v)) } c.ui.Output("") } return nil }
func (c *DestroyCommand) Execute(args []string) error { sysConfig := BuiltinConfig sysConfig.Discover() config, err := padstone.LoadConfig(c.Args.ConfigDir) if err != nil { return err } storage := &tfmodcfg.FolderStorage{ StorageDir: ".padstone", } stateFile, err := os.Open(c.Args.StateFile) if err != nil { return fmt.Errorf("error opening state file %s: %s", c.Args.StateFile, err) } state, err := terraform.ReadState(stateFile) if err != nil { return fmt.Errorf("error reading state file %s: %s", c.Args.StateFile, err) } uiHook := &UIHook{ ui: c.ui, verbose: c.Verbose, } stateHook := &StateHook{ OutputFilename: c.Args.StateFile, } variables, err := decodeKVSpecs(c.Args.VarSpecs) if err != nil { return err } ctx := &padstone.Context{ Config: config, State: state, Providers: sysConfig.ProviderFactories(), Provisioners: sysConfig.ProvisionerFactories(), Variables: variables, Hooks: []terraform.Hook{stateHook, uiHook}, UIInput: c.ui, ModuleStorage: storage, } warns, errs := ctx.Validate() for _, warning := range warns { c.ui.Warn(warning) } if len(errs) > 0 { for _, err := range errs { c.ui.Error(err.Error()) } return fmt.Errorf("aborted due to configuration errors.") } err = ctx.Destroy() if err != nil { return err } rootState := ctx.State.RootModule() moduleCount := len(ctx.State.Modules) if moduleCount == 1 && len(rootState.Resources) == 0 { c.ui.Info("All resources destroyed") err := os.Remove(c.Args.StateFile) if err != nil { return fmt.Errorf("Failed to remove state file %s: %s", c.Args.StateFile, err) } } else { c.ui.Warn(fmt.Sprintf("Not all resources were destroyed. State file %s updated to reflect remaining resources.", c.Args.StateFile)) _, err = stateHook.PostStateUpdate(ctx.State) if err != nil { return err } } return nil }