github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/arguments/apply.go (about) 1 package arguments 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/internal/plans" 7 "github.com/hashicorp/terraform/internal/tfdiags" 8 ) 9 10 // Apply represents the command-line arguments for the apply command. 11 type Apply struct { 12 // State, Operation, and Vars are the common extended flags 13 State *State 14 Operation *Operation 15 Vars *Vars 16 17 // AutoApprove skips the manual verification step for the apply operation. 18 AutoApprove bool 19 20 // InputEnabled is used to disable interactive input for unspecified 21 // variable and backend config values. Default is true. 22 InputEnabled bool 23 24 // PlanPath contains an optional path to a stored plan file 25 PlanPath string 26 27 // ViewType specifies which output format to use 28 ViewType ViewType 29 } 30 31 // ParseApply processes CLI arguments, returning an Apply value and errors. 32 // If errors are encountered, an Apply value is still returned representing 33 // the best effort interpretation of the arguments. 34 func ParseApply(args []string) (*Apply, tfdiags.Diagnostics) { 35 var diags tfdiags.Diagnostics 36 apply := &Apply{ 37 State: &State{}, 38 Operation: &Operation{}, 39 Vars: &Vars{}, 40 } 41 42 cmdFlags := extendedFlagSet("apply", apply.State, apply.Operation, apply.Vars) 43 cmdFlags.BoolVar(&apply.AutoApprove, "auto-approve", false, "auto-approve") 44 cmdFlags.BoolVar(&apply.InputEnabled, "input", true, "input") 45 46 var json bool 47 cmdFlags.BoolVar(&json, "json", false, "json") 48 49 if err := cmdFlags.Parse(args); err != nil { 50 diags = diags.Append(tfdiags.Sourceless( 51 tfdiags.Error, 52 "Failed to parse command-line flags", 53 err.Error(), 54 )) 55 } 56 57 args = cmdFlags.Args() 58 if len(args) > 0 { 59 apply.PlanPath = args[0] 60 args = args[1:] 61 } 62 63 if len(args) > 0 { 64 diags = diags.Append(tfdiags.Sourceless( 65 tfdiags.Error, 66 "Too many command line arguments", 67 "Expected at most one positional argument.", 68 )) 69 } 70 71 // JSON view currently does not support input, so we disable it here. 72 if json { 73 apply.InputEnabled = false 74 } 75 76 // JSON view cannot confirm apply, so we require either a plan file or 77 // auto-approve to be specified. We intentionally fail here rather than 78 // override auto-approve, which would be dangerous. 79 if json && apply.PlanPath == "" && !apply.AutoApprove { 80 diags = diags.Append(tfdiags.Sourceless( 81 tfdiags.Error, 82 "Plan file or auto-approve required", 83 "Terraform cannot ask for interactive approval when -json is set. You can either apply a saved plan file, or enable the -auto-approve option.", 84 )) 85 } 86 87 diags = diags.Append(apply.Operation.Parse()) 88 89 switch { 90 case json: 91 apply.ViewType = ViewJSON 92 default: 93 apply.ViewType = ViewHuman 94 } 95 96 return apply, diags 97 } 98 99 // ParseApplyDestroy is a special case of ParseApply that deals with the 100 // "terraform destroy" command, which is effectively an alias for 101 // "terraform apply -destroy". 102 func ParseApplyDestroy(args []string) (*Apply, tfdiags.Diagnostics) { 103 apply, diags := ParseApply(args) 104 105 // So far ParseApply was using the command line options like -destroy 106 // and -refresh-only to determine the plan mode. For "terraform destroy" 107 // we expect neither of those arguments to be set, and so the plan mode 108 // should currently be set to NormalMode, which we'll replace with 109 // DestroyMode here. If it's already set to something else then that 110 // suggests incorrect usage. 111 switch apply.Operation.PlanMode { 112 case plans.NormalMode: 113 // This indicates that the user didn't specify any mode options at 114 // all, which is correct, although we know from the command that 115 // they actually intended to use DestroyMode here. 116 apply.Operation.PlanMode = plans.DestroyMode 117 case plans.DestroyMode: 118 diags = diags.Append(tfdiags.Sourceless( 119 tfdiags.Error, 120 "Invalid mode option", 121 "The -destroy option is not valid for \"terraform destroy\", because this command always runs in destroy mode.", 122 )) 123 case plans.RefreshOnlyMode: 124 diags = diags.Append(tfdiags.Sourceless( 125 tfdiags.Error, 126 "Invalid mode option", 127 "The -refresh-only option is not valid for \"terraform destroy\".", 128 )) 129 default: 130 // This is a non-ideal error message for if we forget to handle a 131 // newly-handled plan mode in Operation.Parse. Ideally they should all 132 // have cases above so we can produce better error messages. 133 diags = diags.Append(tfdiags.Sourceless( 134 tfdiags.Error, 135 "Invalid mode option", 136 fmt.Sprintf("The \"terraform destroy\" command doesn't support %s.", apply.Operation.PlanMode), 137 )) 138 } 139 140 // NOTE: It's also invalid to have apply.PlanPath set in this codepath, 141 // but we don't check that in here because we'll return a different error 142 // message depending on whether the given path seems to refer to a saved 143 // plan file or to a configuration directory. The apply command 144 // implementation itself therefore handles this situation. 145 146 return apply, diags 147 }