github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/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/iaas-resource-provision/iaas-rpc-svchost" 11 "github.com/iaas-resource-provision/iaas-rpc-svchost/auth" 12 "github.com/iaas-resource-provision/iaas-rpc-svchost/disco" 13 "github.com/iaas-resource-provision/iaas-rpc/internal/addrs" 14 "github.com/iaas-resource-provision/iaas-rpc/internal/command" 15 "github.com/iaas-resource-provision/iaas-rpc/internal/command/cliconfig" 16 "github.com/iaas-resource-provision/iaas-rpc/internal/command/views" 17 "github.com/iaas-resource-provision/iaas-rpc/internal/command/webbrowser" 18 "github.com/iaas-resource-provision/iaas-rpc/internal/getproviders" 19 pluginDiscovery "github.com/iaas-resource-provision/iaas-rpc/internal/plugin/discovery" 20 "github.com/iaas-resource-provision/iaas-rpc/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 dataDir := os.Getenv("TF_DATA_DIR") 81 82 meta := command.Meta{ 83 OriginalWorkingDir: originalWorkingDir, 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 OverrideDataDir: dataDir, 98 99 ShutdownCh: makeShutdownCh(), 100 101 ProviderSource: providerSrc, 102 ProviderDevOverrides: providerDevOverrides, 103 UnmanagedProviders: unmanagedProviders, 104 } 105 106 // The command list is included in the terraform -help 107 // output, which is in turn included in the docs at 108 // website/docs/cli/commands/index.html.markdown; if you 109 // add, remove or reclassify commands then consider updating 110 // that to match. 111 112 Commands = map[string]cli.CommandFactory{ 113 "apply": func() (cli.Command, error) { 114 return &command.ApplyCommand{ 115 Meta: meta, 116 }, nil 117 }, 118 119 "console": func() (cli.Command, error) { 120 return &command.ConsoleCommand{ 121 Meta: meta, 122 }, nil 123 }, 124 125 "destroy": func() (cli.Command, error) { 126 return &command.ApplyCommand{ 127 Meta: meta, 128 Destroy: true, 129 }, nil 130 }, 131 132 "env": func() (cli.Command, error) { 133 return &command.WorkspaceCommand{ 134 Meta: meta, 135 LegacyName: true, 136 }, nil 137 }, 138 139 "env list": func() (cli.Command, error) { 140 return &command.WorkspaceListCommand{ 141 Meta: meta, 142 LegacyName: true, 143 }, nil 144 }, 145 146 "env select": func() (cli.Command, error) { 147 return &command.WorkspaceSelectCommand{ 148 Meta: meta, 149 LegacyName: true, 150 }, nil 151 }, 152 153 "env new": func() (cli.Command, error) { 154 return &command.WorkspaceNewCommand{ 155 Meta: meta, 156 LegacyName: true, 157 }, nil 158 }, 159 160 "env delete": func() (cli.Command, error) { 161 return &command.WorkspaceDeleteCommand{ 162 Meta: meta, 163 LegacyName: true, 164 }, nil 165 }, 166 167 "fmt": func() (cli.Command, error) { 168 return &command.FmtCommand{ 169 Meta: meta, 170 }, nil 171 }, 172 173 "get": func() (cli.Command, error) { 174 return &command.GetCommand{ 175 Meta: meta, 176 }, nil 177 }, 178 179 "graph": func() (cli.Command, error) { 180 return &command.GraphCommand{ 181 Meta: meta, 182 }, nil 183 }, 184 185 "import": func() (cli.Command, error) { 186 return &command.ImportCommand{ 187 Meta: meta, 188 }, nil 189 }, 190 191 "init": func() (cli.Command, error) { 192 return &command.InitCommand{ 193 Meta: meta, 194 }, nil 195 }, 196 197 "login": func() (cli.Command, error) { 198 return &command.LoginCommand{ 199 Meta: meta, 200 }, nil 201 }, 202 203 "logout": func() (cli.Command, error) { 204 return &command.LogoutCommand{ 205 Meta: meta, 206 }, nil 207 }, 208 209 "output": func() (cli.Command, error) { 210 return &command.OutputCommand{ 211 Meta: meta, 212 }, nil 213 }, 214 215 "plan": func() (cli.Command, error) { 216 return &command.PlanCommand{ 217 Meta: meta, 218 }, nil 219 }, 220 221 "providers": func() (cli.Command, error) { 222 return &command.ProvidersCommand{ 223 Meta: meta, 224 }, nil 225 }, 226 227 "providers lock": func() (cli.Command, error) { 228 return &command.ProvidersLockCommand{ 229 Meta: meta, 230 }, nil 231 }, 232 233 "providers mirror": func() (cli.Command, error) { 234 return &command.ProvidersMirrorCommand{ 235 Meta: meta, 236 }, nil 237 }, 238 239 "providers schema": func() (cli.Command, error) { 240 return &command.ProvidersSchemaCommand{ 241 Meta: meta, 242 }, nil 243 }, 244 245 "push": func() (cli.Command, error) { 246 return &command.PushCommand{ 247 Meta: meta, 248 }, nil 249 }, 250 251 "refresh": func() (cli.Command, error) { 252 return &command.RefreshCommand{ 253 Meta: meta, 254 }, nil 255 }, 256 257 "show": func() (cli.Command, error) { 258 return &command.ShowCommand{ 259 Meta: meta, 260 }, nil 261 }, 262 263 "taint": func() (cli.Command, error) { 264 return &command.TaintCommand{ 265 Meta: meta, 266 }, nil 267 }, 268 269 "test": func() (cli.Command, error) { 270 return &command.TestCommand{ 271 Meta: meta, 272 }, nil 273 }, 274 275 "validate": func() (cli.Command, error) { 276 return &command.ValidateCommand{ 277 Meta: meta, 278 }, nil 279 }, 280 281 "version": func() (cli.Command, error) { 282 return &command.VersionCommand{ 283 Meta: meta, 284 Version: Version, 285 VersionPrerelease: VersionPrerelease, 286 Platform: getproviders.CurrentPlatform, 287 CheckFunc: commandVersionCheck, 288 }, nil 289 }, 290 291 "untaint": func() (cli.Command, error) { 292 return &command.UntaintCommand{ 293 Meta: meta, 294 }, nil 295 }, 296 297 "workspace": func() (cli.Command, error) { 298 return &command.WorkspaceCommand{ 299 Meta: meta, 300 }, nil 301 }, 302 303 "workspace list": func() (cli.Command, error) { 304 return &command.WorkspaceListCommand{ 305 Meta: meta, 306 }, nil 307 }, 308 309 "workspace select": func() (cli.Command, error) { 310 return &command.WorkspaceSelectCommand{ 311 Meta: meta, 312 }, nil 313 }, 314 315 "workspace show": func() (cli.Command, error) { 316 return &command.WorkspaceShowCommand{ 317 Meta: meta, 318 }, nil 319 }, 320 321 "workspace new": func() (cli.Command, error) { 322 return &command.WorkspaceNewCommand{ 323 Meta: meta, 324 }, nil 325 }, 326 327 "workspace delete": func() (cli.Command, error) { 328 return &command.WorkspaceDeleteCommand{ 329 Meta: meta, 330 }, nil 331 }, 332 333 //----------------------------------------------------------- 334 // Plumbing 335 //----------------------------------------------------------- 336 337 "force-unlock": func() (cli.Command, error) { 338 return &command.UnlockCommand{ 339 Meta: meta, 340 }, nil 341 }, 342 343 "state": func() (cli.Command, error) { 344 return &command.StateCommand{}, nil 345 }, 346 347 "state list": func() (cli.Command, error) { 348 return &command.StateListCommand{ 349 Meta: meta, 350 }, nil 351 }, 352 353 "state rm": func() (cli.Command, error) { 354 return &command.StateRmCommand{ 355 StateMeta: command.StateMeta{ 356 Meta: meta, 357 }, 358 }, nil 359 }, 360 361 "state mv": func() (cli.Command, error) { 362 return &command.StateMvCommand{ 363 StateMeta: command.StateMeta{ 364 Meta: meta, 365 }, 366 }, nil 367 }, 368 369 "state pull": func() (cli.Command, error) { 370 return &command.StatePullCommand{ 371 Meta: meta, 372 }, nil 373 }, 374 375 "state push": func() (cli.Command, error) { 376 return &command.StatePushCommand{ 377 Meta: meta, 378 }, nil 379 }, 380 381 "state show": func() (cli.Command, error) { 382 return &command.StateShowCommand{ 383 Meta: meta, 384 }, nil 385 }, 386 387 "state replace-provider": func() (cli.Command, error) { 388 return &command.StateReplaceProviderCommand{ 389 StateMeta: command.StateMeta{ 390 Meta: meta, 391 }, 392 }, nil 393 }, 394 } 395 396 PrimaryCommands = []string{ 397 "init", 398 "validate", 399 "plan", 400 "apply", 401 "destroy", 402 } 403 404 HiddenCommands = map[string]struct{}{ 405 "env": struct{}{}, 406 "internal-plugin": struct{}{}, 407 "push": struct{}{}, 408 } 409 410 } 411 412 // makeShutdownCh creates an interrupt listener and returns a channel. 413 // A message will be sent on the channel for every interrupt received. 414 func makeShutdownCh() <-chan struct{} { 415 resultCh := make(chan struct{}) 416 417 signalCh := make(chan os.Signal, 4) 418 signal.Notify(signalCh, ignoreSignals...) 419 signal.Notify(signalCh, forwardSignals...) 420 go func() { 421 for { 422 <-signalCh 423 resultCh <- struct{}{} 424 } 425 }() 426 427 return resultCh 428 } 429 430 func credentialsSource(config *cliconfig.Config) (auth.CredentialsSource, error) { 431 helperPlugins := pluginDiscovery.FindPlugins("credentials", globalPluginDirs()) 432 return config.CredentialsSource(helperPlugins) 433 }