terraspace 0.6.23 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.cody/README.md +2 -0
  3. data/.cody/azurerm/bin/az/configure.sh +5 -1
  4. data/.cody/azurerm/project.rb +4 -0
  5. data/.cody/azurerm/role.rb +0 -1
  6. data/.cody/google/bin/gcloud/configure.sh +2 -1
  7. data/.cody/google/project.rb +4 -0
  8. data/.cody/google/role.rb +0 -1
  9. data/.cody/none/bin/build.sh +15 -0
  10. data/.cody/none/buildspec.yml +10 -0
  11. data/.cody/none/project.rb +2 -0
  12. data/.cody/none/role.rb +4 -0
  13. data/.cody/shared/script/install/terraform.sh +14 -6
  14. data/.cody/unit/buildspec.yml +1 -0
  15. data/.pipedream/pipeline.rb +1 -0
  16. data/CHANGELOG.md +28 -0
  17. data/Gemfile +6 -0
  18. data/README.md +1 -1
  19. data/lib/templates/examples/hcl/module/main.tf +3 -0
  20. data/lib/templates/examples/hcl/module/outputs.tf +4 -0
  21. data/lib/templates/examples/hcl/module/variables.tf +5 -0
  22. data/lib/templates/examples/hcl/stack/main.tf +4 -0
  23. data/lib/templates/examples/hcl/stack/outputs.tf +4 -0
  24. data/lib/templates/examples/hcl/stack/variables.tf +5 -0
  25. data/lib/templates/examples/ruby/module/main.rb +3 -0
  26. data/lib/templates/examples/ruby/module/outputs.rb +4 -0
  27. data/lib/templates/examples/ruby/module/variables.rb +5 -0
  28. data/lib/templates/examples/ruby/stack/main.rb +4 -0
  29. data/lib/templates/examples/ruby/stack/outputs.rb +4 -0
  30. data/lib/templates/examples/ruby/stack/variables.rb +5 -0
  31. data/lib/templates/hcl/project/config/terraform/backend.tf.tt +5 -13
  32. data/lib/templates/hcl/project/config/terraform/provider.tf +4 -14
  33. data/lib/terraspace/autodetect.rb +15 -0
  34. data/lib/terraspace/autoloader.rb +6 -1
  35. data/lib/terraspace/builder.rb +1 -9
  36. data/lib/terraspace/bundle.rb +54 -0
  37. data/lib/terraspace/cli/concern.rb +113 -0
  38. data/lib/terraspace/cli/help/new/example.md +7 -1
  39. data/lib/terraspace/cli/help.rb +7 -8
  40. data/lib/terraspace/cli/new/example.rb +36 -0
  41. data/lib/terraspace/cli/new/helpers/plugin_gem.rb +2 -14
  42. data/lib/terraspace/cli/new/helpers.rb +1 -1
  43. data/lib/terraspace/cli/new/module.rb +1 -1
  44. data/lib/terraspace/cli/new/plugin/helper.rb +1 -1
  45. data/lib/terraspace/cli/new/plugin.rb +1 -1
  46. data/lib/terraspace/cli/new/project.rb +11 -17
  47. data/lib/terraspace/cli/new/sequence.rb +1 -1
  48. data/lib/terraspace/cli/new/source/core.rb +7 -6
  49. data/lib/terraspace/cli/new/source/plugin.rb +2 -2
  50. data/lib/terraspace/cli/new/stack.rb +3 -2
  51. data/lib/terraspace/cli/new/test.rb +12 -2
  52. data/lib/terraspace/cli/new.rb +4 -0
  53. data/lib/terraspace/cli/{check_setup.rb → setup/check.rb} +5 -3
  54. data/lib/terraspace/cli/setup.rb +9 -0
  55. data/lib/terraspace/cli/tfc_concern.rb +1 -1
  56. data/lib/terraspace/cli.rb +34 -27
  57. data/lib/terraspace/command.rb +3 -2
  58. data/lib/terraspace/compiler/commands_concern.rb +0 -8
  59. data/lib/terraspace/compiler/expander/backend.rb +44 -0
  60. data/lib/terraspace/compiler/expander.rb +11 -19
  61. data/lib/terraspace/core.rb +10 -0
  62. data/lib/terraspace/plugin/expander/friendly.rb +1 -0
  63. data/lib/terraspace/plugin/expander/interface.rb +13 -2
  64. data/lib/terraspace/terraform/api/client.rb +1 -1
  65. data/lib/terraspace/terraform/args/custom.rb +11 -6
  66. data/lib/terraspace/terraform/args/pass.rb +110 -0
  67. data/lib/terraspace/terraform/args/{default.rb → thor.rb} +1 -3
  68. data/lib/terraspace/{compiler → terraform/runner}/backend/parser.rb +1 -1
  69. data/lib/terraspace/{compiler → terraform/runner}/backend.rb +14 -1
  70. data/lib/terraspace/terraform/runner/retryer.rb +1 -1
  71. data/lib/terraspace/terraform/runner.rb +25 -15
  72. data/lib/terraspace/terraform/tfc/sync.rb +1 -1
  73. data/lib/terraspace/version.rb +1 -1
  74. data/spec/terraspace/terraform/args/custom_spec.rb +4 -4
  75. data/spec/terraspace/terraform/args/pass_spec.rb +101 -0
  76. data/terraspace.gemspec +2 -4
  77. metadata +46 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9ff791ca3b7b100a8f60caa7a8f8a81e97d45e10317b39643b924cfad6696f6
4
- data.tar.gz: bd57524893eb19164b38bb8e4495a1577e5784094dd03329565c99200551fe56
3
+ metadata.gz: 4d6b5c8b44ff632fd2687d25b1319b11b467affcc4d9220a03ce0316adc9e801
4
+ data.tar.gz: 87c47fee989731e10a314c3b792917eb11141656d6435e3a8ec1083f2e690e24
5
5
  SHA512:
6
- metadata.gz: 80ea2622c03f16a05450b2616a32988c128146cb91319e48bacba6a6ee04c2c6eeae9d006d2f446a5ab91bc1f44fc40e4cdef7ad25ca1b2ff8b42fc8c1703b72
7
- data.tar.gz: 6c6ac8a06236ce3dfd827028f1681da5e9f7197c564c85cbf9d9188dd8940e9cdfe810663d33c505b01d05d68fa74fc6be475fb6ea329a21971a384bc094c261
6
+ metadata.gz: dee89bac4527b8d370cf6c27d145d54345f05878d08cab08220135dfeae1515ef4c7f91eb4f75cfe3aa56e29536da47bc675071573e984fc34fdf41b36034af9
7
+ data.tar.gz: ae59aaa40c073fcc7229519f3b5b9463610ddd0c0fcff0a8b3f8106d52b85147bf19215a2b7fa864034fb8306550010edf31f21634fbd511eca0a077111fe046
data/.cody/README.md CHANGED
@@ -19,6 +19,8 @@ To start a CodeBuild build:
19
19
  cody start --type aws
20
20
  cody start --type azurerm
21
21
  cody start --type google
22
+ cody start --type none
23
+ cody start --type unit
22
24
 
23
25
  To specify a branch:
24
26
 
@@ -3,7 +3,10 @@
3
3
  set -eux
4
4
 
5
5
  mkdir -p ~/.azure
6
- aws secretsmanager get-secret-value --secret-id terraspace/azure-client | jq -r '.SecretString | fromjson' > ~/.azure/app-client.json
6
+
7
+ set +x
8
+ # aws secretsmanager get-secret-value --secret-id terraspace/azure-client | jq -r '.SecretString | fromjson' > ~/.azure/app-client.json
9
+ echo $AZURE_APP_CLIENT_JSON > ~/.azure/app-client.json
7
10
 
8
11
  # ~/.azure/app-client.json
9
12
  export ARM_CLIENT_ID=$(cat ~/.azure/app-client.json | jq -r '.client_id')
@@ -16,6 +19,7 @@ az login --service-principal \
16
19
  --username $ARM_CLIENT_ID \
17
20
  --password $ARM_CLIENT_SECRET \
18
21
  --tenant $ARM_TENANT_ID
22
+ set -x
19
23
 
20
24
  git clone https://github.com/boltops-tools/azure_check.git
21
25
  cd azure_check
@@ -1,2 +1,6 @@
1
1
  github_url("https://github.com/boltops-tools/terraspace.git")
2
2
  linux_image("aws/codebuild/amazonlinux2-x86_64-standard:3.0")
3
+ environment_variables(
4
+ # Used by .cody/azurerm/bin/az/configure.sh
5
+ AZURE_APP_CLIENT_JSON: ssm("/terraspace/#{Cody.env}/azure_app_client_json"),
6
+ )
@@ -1,5 +1,4 @@
1
1
  iam_policy(
2
2
  "logs",
3
- "secretsmanager",
4
3
  "ssm",
5
4
  )
@@ -3,7 +3,8 @@
3
3
  set -eu
4
4
 
5
5
  mkdir -p ~/.gcp
6
- aws secretsmanager get-secret-value --secret-id terraspace/gcloud-credentials | jq '.SecretString | fromjson' > ~/.gcp/credentials.json
6
+ # aws secretsmanager get-secret-value --secret-id terraspace/gcloud-credentials | jq '.SecretString | fromjson' > ~/.gcp/credentials.json
7
+ echo $GOOGLE_CREDS_JSON > ~/.gcp/credentials.json
7
8
 
8
9
  # ~/.gcp/credentials.json
9
10
  export GOOGLE_APPLICATION_CREDENTIALS=~/.gcp/credentials.json
@@ -1,2 +1,6 @@
1
1
  github_url("https://github.com/boltops-tools/terraspace.git")
2
2
  linux_image("aws/codebuild/amazonlinux2-x86_64-standard:3.0")
3
+ environment_variables(
4
+ # Used by .cody/google/bin/gcloud/configure.sh
5
+ GOOGLE_CREDS_JSON: ssm("/terraspace/#{Cody.env}/google_creds_json"),
6
+ )
data/.cody/google/role.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  iam_policy(
2
2
  "logs",
3
- "secretsmanager",
4
3
  "ssm",
5
4
  )
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+
3
+ set -eu
4
+
5
+ # will build from /tmp because terraspace/Gemfile may interfere
6
+ cd /tmp
7
+
8
+ export PATH=~/bin:$PATH # ~/bin/terraspace wrapper
9
+
10
+ set -x
11
+ terraspace new project infra --plugin none --examples
12
+ cd infra
13
+ terraspace new test demo --type stack
14
+ cd app/stacks/demo
15
+ terraspace test
@@ -0,0 +1,10 @@
1
+ version: 0.2
2
+
3
+ phases:
4
+ install:
5
+ runtime-versions:
6
+ ruby: latest
7
+ build:
8
+ commands:
9
+ - .cody/shared/script/install.sh
10
+ - .cody/none/bin/build.sh
@@ -0,0 +1,2 @@
1
+ github_url("https://github.com/boltops-tools/terraspace.git")
2
+ linux_image("aws/codebuild/amazonlinux2-x86_64-standard:3.0")
@@ -0,0 +1,4 @@
1
+ iam_policy(
2
+ "logs",
3
+ "ssm",
4
+ )
@@ -2,10 +2,18 @@
2
2
 
3
3
  set -eu
4
4
 
5
- TERRAFORM_VERSION=0.12.26
5
+ TERRAFORM_VERSION=latest
6
6
 
7
- mkdir /tmp/terraform
8
- cd /tmp/terraform
9
- wget -q https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip
10
- unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip
11
- mv terraform /usr/local/bin
7
+ git clone https://github.com/tfutils/tfenv.git ~/.tfenv
8
+ echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bash_profile
9
+ export PATH="$HOME/.tfenv/bin:$PATH"
10
+ tfenv install $TERRAFORM_VERSION
11
+ tfenv use $TERRAFORM_VERSION
12
+
13
+ # Generate wrapper so dont have to worry about adding .tfenv/bin to PATH in codebuild env
14
+ cat << 'EOL' > /usr/local/bin/terraform
15
+ #!/bin/bash
16
+ export PATH="$HOME/.tfenv/bin:$PATH"
17
+ exec terraform "$@"
18
+ EOL
19
+ chmod +x /usr/local/bin/terraform
@@ -6,4 +6,5 @@ phases:
6
6
  ruby: latest
7
7
  build:
8
8
  commands:
9
+ - .cody/shared/script/install/terraform.sh
9
10
  - .cody/unit/bin/build.sh
@@ -12,6 +12,7 @@ stage "Build" do
12
12
  "terraspace-aws",
13
13
  "terraspace-azurerm",
14
14
  "terraspace-google",
15
+ "terraspace-none",
15
16
  "terraspace-unit",
16
17
  )
17
18
  end
data/CHANGELOG.md CHANGED
@@ -3,6 +3,34 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [0.7.0] - 2021-12-30
7
+ Highlights:
8
+ - Non-cloud provider support
9
+ - Better passthrough terraspace options to terraform. Pretty much all terraform options are now supported.
10
+ - Remove `terraspace_plugin_*` gem dependencies out of core
11
+ - Improve top CLI help: group main commands at top
12
+
13
+ Details:
14
+ - [#168](https://github.com/boltops-tools/terraspace/pull/168) terraspace new example command
15
+ - [#169](https://github.com/boltops-tools/terraspace/pull/169) fix new plugin generator, use right include Helper
16
+ - [#170](https://github.com/boltops-tools/terraspace/pull/170) remove project --test-structure option in favor of terraspace new test --type project
17
+ - [#171](https://github.com/boltops-tools/terraspace/pull/171) improve cli help: group main commands at top
18
+ - [#172](https://github.com/boltops-tools/terraspace/pull/172) better wrap and pass through terraform args
19
+ - [#173](https://github.com/boltops-tools/terraspace/pull/173) remove `terraspace_plugin_*` gem dependencies out of core
20
+ - [#174](https://github.com/boltops-tools/terraspace/pull/174) support non-cloud providers and backends
21
+ - [#175](https://github.com/boltops-tools/terraspace/pull/175) Pass args cleanup
22
+ - [#176](https://github.com/boltops-tools/terraspace/pull/176) fix new example command
23
+ - [#177](https://github.com/boltops-tools/terraspace/pull/177) Shim message
24
+ - [#178](https://github.com/boltops-tools/terraspace/pull/178) fix no backend.tf src file case
25
+ - [#179](https://github.com/boltops-tools/terraspace/pull/179) terraspace check setup command
26
+ - [#180](https://github.com/boltops-tools/terraspace/pull/180) hide check_setup command
27
+ - [#181](https://github.com/boltops-tools/terraspace/pull/181) generator improvements: core examples for plugin=none. creates simple random_pet
28
+ - [#182](https://github.com/boltops-tools/terraspace/pull/182) move backend auto creation to runner stage
29
+ - [#183](https://github.com/boltops-tools/terraspace/pull/183) fix example generator lang option
30
+ - allow --version command to run outside terraspace project
31
+ - allow terraspace -help to work also
32
+ - friendly shim message for gem dependency resolution errors
33
+
6
34
  ## [0.6.23] - 2021-12-18
7
35
  - [#167](https://github.com/boltops-tools/terraspace/pull/167) require active_support properly
8
36
 
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem dependencies in terraspace.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem "terraspace_plugin_aws"
8
+ gem "terraspace_plugin_azurerm"
9
+ gem "terraspace_plugin_google"
10
+ end
data/README.md CHANGED
@@ -16,7 +16,7 @@ Official Docs Site: [terraspace.cloud](https://terraspace.cloud)
16
16
 
17
17
  Quick Start Demo:
18
18
 
19
- [![Watch the video](https://img.boltops.com/boltops/tools/terraspace/youtube/terraspace-quick-start.png)](https://www.youtube.com/watch?v=EZfsBJx8pxQ)
19
+ [![Watch the video](https://img.boltops.com/boltops/tools/terraspace/youtube/terraspace-quick-start.png)](https://learn.boltops.com/courses/terraspace-fundamentals/lessons/terraspace-quick-start)
20
20
 
21
21
  ## Quick Start
22
22
 
@@ -0,0 +1,3 @@
1
+ resource "random_pet" "this" {
2
+ length = var.length
3
+ }
@@ -0,0 +1,4 @@
1
+ output "id" {
2
+ description = "Random pet id"
3
+ value = random_pet.this.id
4
+ }
@@ -0,0 +1,5 @@
1
+ variable "length" {
2
+ type = number
3
+ description = "number of words"
4
+ default = 2
5
+ }
@@ -0,0 +1,4 @@
1
+ module "pet" {
2
+ source = "../../modules/example"
3
+ length = var.length
4
+ }
@@ -0,0 +1,4 @@
1
+ output "pet_id" {
2
+ description = "Pet id"
3
+ value = module.pet.id
4
+ }
@@ -0,0 +1,5 @@
1
+ variable "length" {
2
+ type = number
3
+ description = "number of words"
4
+ default = 2
5
+ }
@@ -0,0 +1,3 @@
1
+ resource("random_pet", "this",
2
+ length: var.length
3
+ )
@@ -0,0 +1,4 @@
1
+ output("id",
2
+ description: "Random pet id",
3
+ value: "${random_pet.this.id}",
4
+ )
@@ -0,0 +1,5 @@
1
+ variable("length",
2
+ type: :number,
3
+ description: "number of words",
4
+ default: 2,
5
+ )
@@ -0,0 +1,4 @@
1
+ module!("pet",
2
+ source: "../../modules/example",
3
+ length: var.length,
4
+ )
@@ -0,0 +1,4 @@
1
+ output("pet_id",
2
+ description: "Pet id",
3
+ value: "${module.pet.id}",
4
+ )
@@ -0,0 +1,5 @@
1
+ variable("length",
2
+ type: :number,
3
+ description: "number of words",
4
+ default: 2,
5
+ )
@@ -1,18 +1,10 @@
1
- # This is where you put your backend declaration. Here are some examples:
1
+ # This is where you put your backend declaration. Example:
2
2
  #
3
3
  # terraform {
4
- # backend "s3" {
5
- # bucket = "<%= options[:bucket] || "terraform-state-:ACCOUNT-:REGION-:ENV" %>"
6
- # key = "<%%= expansion(":REGION/:ENV/:BUILD_DIR/terraform.tfstate") %> # IE: us-west-2/dev/ec2/modules/vpc/terraform.tfstate
7
- # region = "<%%= expansion(":REGION") %>"
8
- # encrypt = true
9
- # dynamodb_table = "terraform_locks"
4
+ # backend "local" {
5
+ # path = "terraform.tfstate"
10
6
  # }
11
7
  # }
12
8
  #
13
- # terraform {
14
- # backend "gcs" {
15
- # bucket = "<%= options[:bucket] || "terraform-state-:PROJECT-:REGION-:ENV" %>"
16
- # prefix = "<%%= expansion(":REGION/:ENV/:BUILD_DIR") %>" # IE: us-central1/dev/modules/vm
17
- # }
18
- # }
9
+ # More examples: https://terraspace.cloud/docs/config/backend/examples/
10
+ #
@@ -1,16 +1,6 @@
1
- # This is where you put your provider declaration. Here are some examples:
1
+ # This is where you put your provider declaration.
2
2
  #
3
- # provider "aws" {
4
- # region = "<%= ENV['AWS_REGION'] || 'us-east-1' %>"
5
- # }
3
+ # If you end up adding a cloud provider, you should also configure a terraspace_plugin_* gem
4
+ # in the Terraspace project Gemfile and run bundle.
6
5
  #
7
- # Docs: https://www.terraform.io/docs/providers/aws/index.html
8
- #
9
- # provider "google" {
10
- # project = "REPLACE_ME"
11
- # region = "us-central1" # update to your region
12
- # zone = "us-central1-a" # update to your zone
13
- # }
14
- #
15
- # Docs: https://www.terraform.io/docs/providers/google/index.html
16
- #
6
+ # See: https://terraspace.cloud/docs/plugins/
@@ -0,0 +1,15 @@
1
+ module Terraspace
2
+ class Autodetect
3
+ def plugin
4
+ plugins = Terraspace::Plugin.meta.keys
5
+ if plugins.size == 1
6
+ plugins.first
7
+ else
8
+ precedence = %w[aws azurerm google]
9
+ precedence.find do |p|
10
+ plugins.include?(p)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,10 @@
1
1
  require "terraspace/bundle"
2
2
  Terraspace::Bundle.setup
3
- require "zeitwerk"
3
+ begin
4
+ require "zeitwerk"
5
+ rescue LoadError => e
6
+ Terraspace::Bundle.handle_already_activated_error(e)
7
+ end
4
8
 
5
9
  module Terraspace
6
10
  # These modules are namespaces for user-defined custom helpers
@@ -38,3 +42,4 @@ module Terraspace
38
42
  end
39
43
  end
40
44
  end
45
+
@@ -8,7 +8,7 @@ module Terraspace
8
8
 
9
9
  def run
10
10
  return if @options[:build] == false
11
- Terraspace::CLI::CheckSetup.check!
11
+ Terraspace::CLI::Setup::Check.check!
12
12
  @mod.root_module = true
13
13
  clean
14
14
  build_dir = Util.pretty_path(@mod.cache_dir)
@@ -20,7 +20,6 @@ module Terraspace
20
20
  run_hooks("terraspace.rb", "build") do
21
21
  check_allow!
22
22
  build_unresolved
23
- auto_create_backend
24
23
  batches = build_batches
25
24
  build_all
26
25
  logger.info "Built in #{build_dir}" unless @options[:quiet] # from terraspace all
@@ -66,13 +65,6 @@ module Terraspace
66
65
  end
67
66
  end
68
67
 
69
- # Auto create after build_unresolved since will need to run state pull for dependencies
70
- def auto_create_backend
71
- return if Terraspace.config.auto_create_backend == false
72
- return unless requires_backend?
73
- Terraspace::Compiler::Backend.new(@mod).create
74
- end
75
-
76
68
  def clean
77
69
  Compiler::Cleaner.new(@mod, @options).clean if clean?
78
70
  end
@@ -55,6 +55,60 @@ module Terraspace
55
55
  [:default, Terraspace.env.to_sym]
56
56
  end
57
57
 
58
+ # When there are gem dependency issues, requiring zeitwerk with this debugging code
59
+ # begin
60
+ # require "zeitwerk"
61
+ # rescue LoadError => e
62
+ # puts "#{e.class}: #{e.message}"
63
+ # exit 1
64
+ # end
65
+ #
66
+ # Produces:
67
+ #
68
+ # You have already activated faraday 1.8.0, but your Gemfile requires faraday 1.7.2. Prepending `bundle exec` to your command may solve this.
69
+ # LoadError: cannot load such file -- zeitwerk
70
+ #
71
+ # Sadly, the captured exception only contains this info:
72
+ #
73
+ # LoadError: cannot load such file -- zeitwerk
74
+ #
75
+ # The useful "already activated" info that shows gem dependencies issues. Example:
76
+ #
77
+ # You have already activated faraday 1.8.0, but your Gemfile requires faraday 1.7.2. Prepending `bundle exec` to your command may solve this.
78
+ #
79
+ # Is printed to stdout earlier and before exception.
80
+ #
81
+ # So making an assumption that a zeitwerk LoadError is due to gem dependencies issue.
82
+ # It's not ideal, but think this is ok.
83
+ #
84
+ # Note: Not checking shim upon install because it wont be a good user experience
85
+ # to check for a shim unless this error actually occurs.
86
+ #
87
+ # Only been able to reproduce this error for a gem install with: alpine
88
+ # The standalone install already has a shim wrapper.
89
+ #
90
+ def handle_already_activated_error(e)
91
+ # color is not yet available
92
+ puts "ERROR: #{e.class}: #{e.message}" if ENV['TS_DEBUG_ALREADY_ACTIVATED']
93
+ check_shim!
94
+ exit 1
95
+ end
96
+
97
+ def check_shim!
98
+ return unless File.exist?("Gemfile")
99
+ $stderr.puts <<~EOL
100
+ Looks like there are issues trying to resolve gem dependencies.
101
+
102
+ To resolve this, you can generate a shim:
103
+
104
+ terraspace new shim
105
+
106
+ You only have to do this one time.
107
+
108
+ More info: https://terraspace.cloud/docs/install/shim/
109
+ EOL
110
+ end
111
+
58
112
  extend self
59
113
  end
60
114
  end
@@ -0,0 +1,113 @@
1
+ class Terraspace::CLI
2
+ module Concern
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ # So the Thor::Parser::Options#parse allows flag switch shorthand notation. IE:
7
+ #
8
+ # command -abc
9
+ #
10
+ # Is same as:
11
+ #
12
+ # command -a -b -c
13
+ #
14
+ # This messes up the options like -destroy.
15
+ #
16
+ # terraspace plan -destroy
17
+ #
18
+ # Since only a single dash (-) is passed. It's interpreted as a bunch of flag switches.
19
+ # Providing -- works just fine
20
+ #
21
+ # terraspace plan --destroy
22
+ #
23
+ # But it'll be nice if user can use -destroy or --destroy
24
+ #
25
+ # Interestingly, -no-color won't be interpreted by Thor as switch flag due to the - inbetween.
26
+ #
27
+ # Looked into the Thor code:
28
+ #
29
+ # Thor::Parser::Options#parse https://github.com/rails/thor/blob/5c666b4c25e748e57eec2d529d94c5059030979e/lib/thor/parser/options.rb#L88
30
+ # Thor::Parser::Options#current_is_switch? https://github.com/rails/thor/blob/5c666b4c25e748e57eec2d529d94c5059030979e/lib/thor/parser/options.rb#L165
31
+ #
32
+ # Overriding the current_is_switch? is dirtier than overriding start
33
+ # and adjusting the argv before passing to Thor.
34
+ #
35
+ # There are only so few Terraform boolean options that are single words. To find (fish shell)
36
+ #
37
+ # for i in init validate plan apply destroy console fmt force-unlock get graph import login logout output providers refresh show state taint test untaint version workspace ; echo "$i:" ; terraform $i -h | grep '^ -' ; end
38
+ # for i in init validate plan apply destroy console fmt force-unlock get graph import login logout output providers refresh show state taint test untaint version workspace ; echo "$i:" ; terraform $i -h | grep '^ -' | grep -v = | sed 's/ -//' | grep -v - | sed -r 's/\s+.*//' | sed 's/^/ /' ; end
39
+ # for i in init validate plan apply destroy console fmt force-unlock get graph import login logout output providers refresh show state taint test untaint version workspace ; terraform $i -h | grep '^ -' | grep -v = | sed 's/ -//' | grep -v - | sed -r 's/\s+.*//' ; end | sort | uniq
40
+ #
41
+ def start(argv)
42
+ # Note: help is for terraspace -help
43
+ single_word_boolean_args = %w[
44
+ check
45
+ destroy
46
+ diff
47
+ force
48
+ help
49
+ json
50
+ raw
51
+ reconfigure
52
+ recursive
53
+ upgrade
54
+ ]
55
+ args = single_word_boolean_args.map { |s| "-#{s}" }
56
+ argv.map! do |arg|
57
+ if args.include?(arg)
58
+ # Ensure double dash (--).
59
+ # Later in Terraspace::Terraform::Args::Pass#args a single dash (-) is ensured.
60
+ "-#{arg}" # IE: -destroy => --destroy
61
+ else
62
+ arg
63
+ end
64
+ end
65
+ super(argv)
66
+ end
67
+
68
+ def main_commands
69
+ %w[
70
+ all
71
+ build
72
+ bundle
73
+ down
74
+ list
75
+ new
76
+ plan
77
+ seed
78
+ up
79
+ ]
80
+ end
81
+
82
+ def help(shell, subcommand)
83
+ list = printable_commands(true, subcommand)
84
+ list.sort! { |a, b| a[0] <=> b[0] }
85
+ filter = Proc.new do |command, desc|
86
+ main_commands.detect { |name| command =~ Regexp.new("^terraspace #{name}") }
87
+ end
88
+ main = list.select(&filter)
89
+ other = list.reject(&filter)
90
+
91
+ shell.say <<~EOL
92
+ Usage: terraspace COMMAND [args]
93
+
94
+ The available commands are listed below.
95
+ The primary workflow commands are given first, followed by
96
+ less common or more advanced commands.
97
+ EOL
98
+ shell.say "\nMain Commands:\n\n"
99
+ shell.print_table(main, indent: 2, truncate: true)
100
+ shell.say "\nOther Commands:\n\n"
101
+ shell.print_table(other, indent: 2, truncate: true)
102
+ shell.say <<~EOL
103
+
104
+ For more help on each command, you can use the -h option. Example:
105
+
106
+ terraspace up -h
107
+
108
+ CLI Reference also available at: https://terraspace.cloud/reference/
109
+ EOL
110
+ end
111
+ end
112
+ end
113
+ end
@@ -1,8 +1,14 @@
1
1
  ## Example
2
2
 
3
- => Creating test for new module: example
3
+ $ terraspace new example
4
+ => Creating new module called example
4
5
  create app/modules/example
5
6
  create app/modules/example/main.tf
6
7
  create app/modules/example/outputs.tf
7
8
  create app/modules/example/variables.tf
9
+ => Creating new stack called demo
10
+ create app/stacks/demo
11
+ create app/stacks/demo/main.tf
12
+ create app/stacks/demo/outputs.tf
13
+ create app/stacks/demo/variables.tf
8
14
  $
@@ -1,11 +1,10 @@
1
1
  class Terraspace::CLI
2
- class Help
3
- class << self
4
- def text(namespaced_command)
5
- path = namespaced_command.to_s.gsub(':','/')
6
- path = File.expand_path("../help/#{path}.md", __FILE__)
7
- IO.read(path) if File.exist?(path)
8
- end
2
+ module Help
3
+ def text(namespaced_command)
4
+ path = namespaced_command.to_s.gsub(':','/')
5
+ path = File.expand_path("../help/#{path}.md", __FILE__)
6
+ IO.read(path) if File.exist?(path)
9
7
  end
8
+ extend self
10
9
  end
11
- end
10
+ end