github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/commands.go (about) 1 package main 2 3 import ( 4 "os" 5 "os/signal" 6 7 "github.com/mitchellh/cli" 8 9 "github.com/hashicorp/go-plugin" 10 svchost "github.com/hashicorp/terraform-svchost" 11 "github.com/hashicorp/terraform-svchost/auth" 12 "github.com/hashicorp/terraform-svchost/disco" 13 "github.com/hashicorp/terraform/internal/addrs" 14 "github.com/hashicorp/terraform/internal/command" 15 "github.com/hashicorp/terraform/internal/command/cliconfig" 16 "github.com/hashicorp/terraform/internal/command/views" 17 "github.com/hashicorp/terraform/internal/command/webbrowser" 18 "github.com/hashicorp/terraform/internal/getproviders" 19 pluginDiscovery "github.com/hashicorp/terraform/internal/plugin/discovery" 20 "github.com/hashicorp/terraform/internal/terminal" 21 ) 22 23 // runningInAutomationEnvName gives the name of an environment variable that 24 // can be set to any non-empty value in order to suppress certain messages 25 // that assume that Terraform is being run from a command prompt. 26 const runningInAutomationEnvName = "TF_IN_AUTOMATION" 27 28 // Commands is the mapping of all the available Terraform commands. 29 var Commands map[string]cli.CommandFactory 30 31 // PrimaryCommands is an ordered sequence of the top-level commands (not 32 // subcommands) that we emphasize at the top of our help output. This is 33 // ordered so that we can show them in the typical workflow order, rather 34 // than in alphabetical order. Anything not in this sequence or in the 35 // HiddenCommands set appears under "all other commands". 36 var PrimaryCommands []string 37 38 // HiddenCommands is a set of top-level commands (not subcommands) that are 39 // not advertised in the top-level help at all. This is typically because 40 // they are either just stubs that return an error message about something 41 // no longer being supported or backward-compatibility aliases for other 42 // commands. 43 // 44 // No commands in the PrimaryCommands sequence should also appear in the 45 // HiddenCommands set, because that would be rather silly. 46 var HiddenCommands map[string]struct{} 47 48 // Ui is the cli.Ui used for communicating to the outside world. 49 var Ui cli.Ui 50 51 func initCommands( 52 originalWorkingDir string, 53 streams *terminal.Streams, 54 config *cliconfig.Config, 55 services *disco.Disco, 56 providerSrc getproviders.Source, 57 providerDevOverrides map[addrs.Provider]getproviders.PackageLocalDir, 58 unmanagedProviders map[addrs.Provider]*plugin.ReattachConfig, 59 ) { 60 var inAutomation bool 61 if v := os.Getenv(runningInAutomationEnvName); v != "" { 62 inAutomation = true 63 } 64 65 for userHost, hostConfig := range config.Hosts { 66 host, err := svchost.ForComparison(userHost) 67 if err != nil { 68 // We expect the config was already validated by the time we get 69 // here, so we'll just ignore invalid hostnames. 70 continue 71 } 72 services.ForceHostServices(host, hostConfig.Services) 73 } 74 75 configDir, err := cliconfig.ConfigDir() 76 if err != nil { 77 configDir = "" // No config dir available (e.g. looking up a home directory failed) 78 } 79 80 wd := WorkingDir(originalWorkingDir, os.Getenv("TF_DATA_DIR")) 81 82 meta := command.Meta{ 83 WorkingDir: wd, 84 Streams: streams, 85 View: views.NewView(streams).SetRunningInAutomation(inAutomation), 86 87 Color: true, 88 GlobalPluginDirs: globalPluginDirs(), 89 Ui: Ui, 90 91 Services: services, 92 BrowserLauncher: webbrowser.NewNativeLauncher(), 93 94 RunningInAutomation: inAutomation, 95 CLIConfigDir: configDir, 96 PluginCacheDir: config.PluginCacheDir, 97 98 ShutdownCh: makeShutdownCh(), 99 100 ProviderSource: providerSrc, 101 ProviderDevOverrides: providerDevOverrides, 102 UnmanagedProviders: unmanagedProviders, 103 104 AllowExperimentalFeatures: ExperimentsAllowed(), 105 } 106 107 // The command list is included in the terraform -help 108 // output, which is in turn included in the docs at 109 // website/docs/cli/commands/index.html.markdown; if you 110 // add, remove or reclassify commands then consider updating 111 // that to match. 112 113 Commands = map[string]cli.CommandFactory{ 114 "apply": func() (cli.Command, error) { 115 return &command.ApplyCommand{ 116 Meta: meta, 117 }, nil 118 }, 119 120 "console": func() (cli.Command, error) { 121 return &command.ConsoleCommand{ 122 Meta: meta, 123 }, nil 124 }, 125 126 "destroy": func() (cli.Command, error) { 127 return &command.ApplyCommand{ 128 Meta: meta, 129 Destroy: true, 130 }, nil 131 }, 132 133 "env": func() (cli.Command, error) { 134 return &command.WorkspaceCommand{ 135 Meta: meta, 136 LegacyName: true, 137 }, nil 138 }, 139 140 "env list": func() (cli.Command, error) { 141 return &command.WorkspaceListCommand{ 142 Meta: meta, 143 LegacyName: true, 144 }, nil 145 }, 146 147 "env select": func() (cli.Command, error) { 148 return &command.WorkspaceSelectCommand{ 149 Meta: meta, 150 LegacyName: true, 151 }, nil 152 }, 153 154 "env new": func() (cli.Command, error) { 155 return &command.WorkspaceNewCommand{ 156 Meta: meta, 157 LegacyName: true, 158 }, nil 159 }, 160 161 "env delete": func() (cli.Command, error) { 162 return &command.WorkspaceDeleteCommand{ 163 Meta: meta, 164 LegacyName: true, 165 }, nil 166 }, 167 168 "fmt": func() (cli.Command, error) { 169 return &command.FmtCommand{ 170 Meta: meta, 171 }, nil 172 }, 173 174 "get": func() (cli.Command, error) { 175 return &command.GetCommand{ 176 Meta: meta, 177 }, nil 178 }, 179 180 "graph": func() (cli.Command, error) { 181 return &command.GraphCommand{ 182 Meta: meta, 183 }, nil 184 }, 185 186 "import": func() (cli.Command, error) { 187 return &command.ImportCommand{ 188 Meta: meta, 189 }, nil 190 }, 191 192 "init": func() (cli.Command, error) { 193 return &command.InitCommand{ 194 Meta: meta, 195 }, nil 196 }, 197 198 "login": func() (cli.Command, error) { 199 return &command.LoginCommand{ 200 Meta: meta, 201 }, nil 202 }, 203 204 "logout": func() (cli.Command, error) { 205 return &command.LogoutCommand{ 206 Meta: meta, 207 }, nil 208 }, 209 210 "output": func() (cli.Command, error) { 211 return &command.OutputCommand{ 212 Meta: meta, 213 }, nil 214 }, 215 216 "plan": func() (cli.Command, error) { 217 return &command.PlanCommand{ 218 Meta: meta, 219 }, nil 220 }, 221 222 "providers": func() (cli.Command, error) { 223 return &command.ProvidersCommand{ 224 Meta: meta, 225 }, nil 226 }, 227 228 "providers lock": func() (cli.Command, error) { 229 return &command.ProvidersLockCommand{ 230 Meta: meta, 231 }, nil 232 }, 233 234 "providers mirror": func() (cli.Command, error) { 235 return &command.ProvidersMirrorCommand{ 236 Meta: meta, 237 }, nil 238 }, 239 240 "providers schema": func() (cli.Command, error) { 241 return &command.ProvidersSchemaCommand{ 242 Meta: meta, 243 }, nil 244 }, 245 246 "push": func() (cli.Command, error) { 247 return &command.PushCommand{ 248 Meta: meta, 249 }, nil 250 }, 251 252 "refresh": func() (cli.Command, error) { 253 return &command.RefreshCommand{ 254 Meta: meta, 255 }, nil 256 }, 257 258 "show": func() (cli.Command, error) { 259 return &command.ShowCommand{ 260 Meta: meta, 261 }, nil 262 }, 263 264 "taint": func() (cli.Command, error) { 265 return &command.TaintCommand{ 266 Meta: meta, 267 }, nil 268 }, 269 270 "test": func() (cli.Command, error) { 271 return &command.TestCommand{ 272 Meta: meta, 273 }, nil 274 }, 275 276 "validate": func() (cli.Command, error) { 277 return &command.ValidateCommand{ 278 Meta: meta, 279 }, nil 280 }, 281 282 "version": func() (cli.Command, error) { 283 return &command.VersionCommand{ 284 Meta: meta, 285 Version: Version, 286 VersionPrerelease: VersionPrerelease, 287 Platform: getproviders.CurrentPlatform, 288 CheckFunc: commandVersionCheck, 289 }, nil 290 }, 291 292 "untaint": func() (cli.Command, error) { 293 return &command.UntaintCommand{ 294 Meta: meta, 295 }, nil 296 }, 297 298 "workspace": func() (cli.Command, error) { 299 return &command.WorkspaceCommand{ 300 Meta: meta, 301 }, nil 302 }, 303 304 "workspace list": func() (cli.Command, error) { 305 return &command.WorkspaceListCommand{ 306 Meta: meta, 307 }, nil 308 }, 309 310 "workspace select": func() (cli.Command, error) { 311 return &command.WorkspaceSelectCommand{ 312 Meta: meta, 313 }, nil 314 }, 315 316 "workspace show": func() (cli.Command, error) { 317 return &command.WorkspaceShowCommand{ 318 Meta: meta, 319 }, nil 320 }, 321 322 "workspace new": func() (cli.Command, error) { 323 return &command.WorkspaceNewCommand{ 324 Meta: meta, 325 }, nil 326 }, 327 328 "workspace delete": func() (cli.Command, error) { 329 return &command.WorkspaceDeleteCommand{ 330 Meta: meta, 331 }, nil 332 }, 333 334 //----------------------------------------------------------- 335 // Plumbing 336 //----------------------------------------------------------- 337 338 "force-unlock": func() (cli.Command, error) { 339 return &command.UnlockCommand{ 340 Meta: meta, 341 }, nil 342 }, 343 344 "state": func() (cli.Command, error) { 345 return &command.StateCommand{}, nil 346 }, 347 348 "state list": func() (cli.Command, error) { 349 return &command.StateListCommand{ 350 Meta: meta, 351 }, nil 352 }, 353 354 "state rm": func() (cli.Command, error) { 355 return &command.StateRmCommand{ 356 StateMeta: command.StateMeta{ 357 Meta: meta, 358 }, 359 }, nil 360 }, 361 362 "state mv": func() (cli.Command, error) { 363 return &command.StateMvCommand{ 364 StateMeta: command.StateMeta{ 365 Meta: meta, 366 }, 367 }, nil 368 }, 369 370 "state pull": func() (cli.Command, error) { 371 return &command.StatePullCommand{ 372 Meta: meta, 373 }, nil 374 }, 375 376 "state push": func() (cli.Command, error) { 377 return &command.StatePushCommand{ 378 Meta: meta, 379 }, nil 380 }, 381 382 "state show": func() (cli.Command, error) { 383 return &command.StateShowCommand{ 384 Meta: meta, 385 }, nil 386 }, 387 388 "state replace-provider": func() (cli.Command, error) { 389 return &command.StateReplaceProviderCommand{ 390 StateMeta: command.StateMeta{ 391 Meta: meta, 392 }, 393 }, nil 394 }, 395 } 396 397 PrimaryCommands = []string{ 398 "init", 399 "validate", 400 "plan", 401 "apply", 402 "destroy", 403 } 404 405 HiddenCommands = map[string]struct{}{ 406 "env": struct{}{}, 407 "internal-plugin": struct{}{}, 408 "push": struct{}{}, 409 } 410 411 } 412 413 // makeShutdownCh creates an interrupt listener and returns a channel. 414 // A message will be sent on the channel for every interrupt received. 415 func makeShutdownCh() <-chan struct{} { 416 resultCh := make(chan struct{}) 417 418 signalCh := make(chan os.Signal, 4) 419 signal.Notify(signalCh, ignoreSignals...) 420 signal.Notify(signalCh, forwardSignals...) 421 go func() { 422 for { 423 <-signalCh 424 resultCh <- struct{}{} 425 } 426 }() 427 428 return resultCh 429 } 430 431 func credentialsSource(config *cliconfig.Config) (auth.CredentialsSource, error) { 432 helperPlugins := pluginDiscovery.FindPlugins("credentials", globalPluginDirs()) 433 return config.CredentialsSource(helperPlugins) 434 }