terraspace-bundler 0.2.0 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +9 -89
  4. data/lib/terraspace_bundler.rb +1 -0
  5. data/lib/terraspace_bundler/cli/bundle.rb +4 -2
  6. data/lib/terraspace_bundler/cli/help/bundle/info.md +1 -1
  7. data/lib/terraspace_bundler/cli/purge_cache.rb +20 -2
  8. data/lib/terraspace_bundler/config.rb +3 -2
  9. data/lib/terraspace_bundler/core.rb +10 -0
  10. data/lib/terraspace_bundler/dsl/syntax.rb +13 -9
  11. data/lib/terraspace_bundler/exporter.rb +25 -19
  12. data/lib/terraspace_bundler/exporter/base.rb +6 -0
  13. data/lib/terraspace_bundler/exporter/copy.rb +25 -0
  14. data/lib/terraspace_bundler/exporter/stacks.rb +14 -0
  15. data/lib/terraspace_bundler/exporter/stacks/base.rb +5 -0
  16. data/lib/terraspace_bundler/exporter/stacks/rewrite.rb +57 -0
  17. data/lib/terraspace_bundler/exporter/stacks/stack.rb +77 -0
  18. data/lib/terraspace_bundler/lockfile.rb +4 -6
  19. data/lib/terraspace_bundler/lockfile/version_comparer.rb +25 -12
  20. data/lib/terraspace_bundler/lockfile/yamler.rb +1 -1
  21. data/lib/terraspace_bundler/mod.rb +11 -17
  22. data/lib/terraspace_bundler/mod/downloader.rb +24 -5
  23. data/lib/terraspace_bundler/mod/path_concern.rb +9 -0
  24. data/lib/terraspace_bundler/mod/props_builder.rb +17 -4
  25. data/lib/terraspace_bundler/mod/registry.rb +4 -1
  26. data/lib/terraspace_bundler/mod/stack_concern.rb +45 -0
  27. data/lib/terraspace_bundler/{installer.rb → runner.rb} +5 -5
  28. data/lib/terraspace_bundler/syncer.rb +6 -7
  29. data/lib/terraspace_bundler/terrafile.rb +1 -2
  30. data/lib/terraspace_bundler/util/git.rb +10 -4
  31. data/lib/terraspace_bundler/util/sure.rb +22 -0
  32. data/lib/terraspace_bundler/version.rb +1 -1
  33. data/spec/fixtures/rewrite/example-subfolder.tf +3 -0
  34. data/spec/fixtures/rewrite/module-subfolder.tf +3 -0
  35. data/spec/fixtures/rewrite/no-leading.tf +3 -0
  36. data/spec/fixtures/rewrite/no-path.tf +8 -0
  37. data/spec/fixtures/rewrite/no-spaces.tf +3 -0
  38. data/spec/fixtures/rewrite/normal.tf +3 -0
  39. data/spec/fixtures/rewrite/spaces.tf +3 -0
  40. data/spec/fixtures/rewrite/trailing-slash.tf +3 -0
  41. data/spec/spec_helper.rb +4 -0
  42. data/spec/terraform_bundler/exporter/stacks/rewrite_spec.rb +86 -0
  43. data/spec/terraform_bundler/mod_spec.rb +75 -0
  44. data/spec/terraform_bundler/runner_spec.rb +1 -1
  45. metadata +32 -6
  46. data/lib/terraspace_bundler/cli/runner.rb +0 -7
  47. data/lib/terraspace_bundler/dsl/concern.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 500271ff2f8e5799a55febd3ec25261bcf4126bff456b83360ae0e2a96bb6357
4
- data.tar.gz: ee45f81805b893d5287fdea6777c9b28ac39936273806c3d97275f6c314a8cd1
3
+ metadata.gz: 120ab895b524973b2a5a6367f76d8d1f8794cbc5957abae90ab11532833b8620
4
+ data.tar.gz: 55c69457dbd4fd1bdfce68b1432bcab70fea3d28805f28fc06961fe1c534c149
5
5
  SHA512:
6
- metadata.gz: 94af4d341ed3e43445bf2eb0eae1e3383fe064a6df708c449658b8eb5a958163a225be2ddae121356573ae7e099e87669c5cb9c54808423b9db685faf27d7837
7
- data.tar.gz: d68d1825f89b91ac4d9ad7525a4b4b95cc709ce1e2f3c10d83aa6ad5c6b27a89b3c6ae1ad9bc1ee3179b08345ac73fc551d1467769f702cc43d69b6f3b38b577
6
+ metadata.gz: 024b2f949df4eccfbdd5eaa7ce5b56a60ffc8f48f98044edd38408bd6f87a6f1e87f6b4fbcab54871884489c8742a7a92586eea27233e169cd2ea06c154bb8dc
7
+ data.tar.gz: 2270365d4fea228f1170601e2b02e54e9ccad230ed1dee044b9db134c0bd957f0e50fee715530ec9b1e976f174078e183cb0d598ca24eaf92ebe7f4ccc2d53e9
data/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
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.3.4] - 2021-04-15
7
+ - [#11](https://github.com/boltops-tools/terraspace-bundler/pull/11) improve registry dectection and gitlab repository support
8
+
9
+ ## [0.3.3] - 2021-02-24
10
+ - [#8](https://github.com/boltops-tools/terraspace-bundler/pull/8) fix https sources
11
+ - [#9](https://github.com/boltops-tools/terraspace-bundler/pull/9) Git checkout retry with v
12
+
13
+ ## [0.3.2]
14
+ - #4 only purge and export explicit mods
15
+ - are you sure prompt for purge_cache
16
+ - clean up update mode
17
+
18
+ ## [0.3.1]
19
+ - #3 all_stacks: only consider dirs
20
+
21
+ ## [0.3.0]
22
+ - #2 bundle improvements
23
+ - change `base_clone_url` default from `git@github.com:` to `https://github.com/`
24
+ - mod-level stack option
25
+ - terrafile-level stack_options
26
+ - rename terrafile-level option to export_to
27
+
6
28
  ## [0.2.0]
7
29
  - #1 Rework implementation. Better Terrafile syncing
8
30
  - clearer implementation: Terrafile and Lockfile classes build standard mods object.
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # terraspace-bundler
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/terraspace-bundler.png)](http://badge.fury.io/rb/terraspace-bundler)
4
+
5
+ [![BoltOps Badge](https://img.boltops.com/boltops/badges/boltops-badge.png)](https://www.boltops.com)
6
+
3
7
  Bundles terraform modules based on a `Terrafile` to the `vendor/modules` folder. Used by the [Terraspace Terraform Framework](https://terraspace.cloud/).
4
8
 
5
9
  ## Usage
@@ -7,14 +11,13 @@ Bundles terraform modules based on a `Terrafile` to the `vendor/modules` folder.
7
11
  Create a `Terrafile` file:
8
12
 
9
13
  ```ruby
10
- org "boltopspro" # set default org
14
+ org "boltops-tools" # set default org
11
15
 
12
16
  # GitHub repo with default org
13
- mod "elb", source: "terraform-aws-elb", version: "master"
14
- mod "ec2", source: "terraform-aws-ec2", version: "branch-name"
17
+ mod "s3", source: "terraform-aws-s3", version: "master"
15
18
 
16
19
  # GitHub repo with explicit org
17
- mod "rds", source: "boltopspro/terraform-aws-rds", version: "v0.1.0"
20
+ # mod "elasticache", source: "boltopspro/terraform-aws-elasticache"
18
21
 
19
22
  # Terraform registry
20
23
  mod "sg", source: "terraform-aws-modules/security-group/aws", version: "3.10.0"
@@ -26,90 +29,7 @@ Running `terraspace bundle` creates the `Terrafile.lock` file, which locks the v
26
29
 
27
30
  terraspace bundle
28
31
 
29
- ## Updating
30
-
31
- To update all the locked versions in `Terrafile.lock` run `terraspace bundle update`. You can also delete the `Terrafile.lock` file first.
32
-
33
- terraspace bundle update
34
-
35
- You can selectively update multiple modules:
36
-
37
- terraspace bundle update MODS
38
- terraspace bundle update mod1 mod2
39
-
40
- ## List & Info
41
-
42
- terraspace bundle list
43
- terraspace bundle info mod1
44
-
45
- ## DSL Methods
46
-
47
- Some of these are methods that apply globally at the Terrafile level. Some of these are options that apply the at the mod method level.
48
-
49
- ### Terrafile level
50
-
51
- Name | Description | Default
52
- --- | --- | ---
53
- base_clone_url | Base clone url to use | git@gihtub.com:
54
- export_path | Where the modules get exported to saved to. | vendor/modules
55
- export_purge | Where or not to clean up all existing exported modules folder first. | true
56
-
57
- ### Mod Method level
58
-
59
- Name | Description | Default
60
- --- | --- | ---
61
- subfolder | The subfolder where the module lives within the repo. | nil
62
- export_to | Overrides the export_path Terrafile level option. With this one-off option, other modules in this folder will not be purged. | nil
63
-
64
- Examples of some of the options are below:
65
-
66
- ### base url
67
-
68
- The base url used for clone is `git@github.com:`. You can change it with `base_url`, example:
69
-
70
- ```ruby
71
- base_url "https://github.com/" # default base url for git clone
72
- # ...
73
- ```
74
-
75
- ### export_path
76
-
77
- The default export path is `vendor/modules`, you can change it:
78
-
79
- ```ruby
80
- export_path "app/modules"
81
- # ...
82
- ```
83
-
84
- ## prune
85
-
86
- The `terraspace bundle` commands removes all files in the export_path, `vendor/modules`, by default. You can disable this behavior with:
87
-
88
- ```ruby
89
- export_purge false
90
- # ...
91
- ```
92
-
93
- ### subfolder
94
-
95
- The default export path is `vendor/modules`, you can change it:
96
-
97
- ```ruby
98
- # ...
99
- mod "s3", source: "terraform-aws-s3", subfolder: "path/to/module/s3"
100
- ```
101
-
102
- ## Config Options
103
-
104
- You can also configure some behavior with `TB.config`. IE: `TB.config.terrafile = "/path/to/Terrafile"`
105
-
106
- Name | Description | Default
107
- --- | --- | ---
108
- base_clone_url | Base git url to use for cloning | git@github.com:
109
- export_path | Where to export the modules to. Can also be set with the env var TB_EXPORT_PATH | vendor/modules
110
- export_purge | Whether or not to prune all the modules | true
111
- logger | Logger instance
112
- terrafile | The Terrafile path. Can also be set with the env TB_TERRAFILE || "Terrafile"
32
+ For more detailed usage instructions refer to the [Terraspace Terrafile docs](https://terraspace.cloud/docs/terrafile/options/)
113
33
 
114
34
  ## Installation
115
35
 
@@ -123,7 +43,7 @@ To install:
123
43
  * Handles updating the `Terrafile.lock` based on the `Terrafile`
124
44
  * Others running the `terraspace bundle install` will install the exact same module versions based the `Terrafile.lock`.
125
45
  * To update `Terraform.lock` run `terraspace bundle update`.
126
- * The repos are downloaded to `/tmp/terraspace-bundler` area as a cache. Delete the cache by running `terraspace bundle purge_cache`.
46
+ * The repos are downloaded to the `/tmp/terraspace-bundler` area as a cache. Delete the cache by running `terraspace bundle purge_cache`.
127
47
 
128
48
  ## Contributing
129
49
 
@@ -7,6 +7,7 @@ require "dsl_evaluator"
7
7
  require "fileutils"
8
8
  require "memoist"
9
9
  require "rainbow/ext/string"
10
+ require "singleton"
10
11
  require "terraspace_bundler/version"
11
12
  require "yaml"
12
13
 
@@ -22,11 +22,12 @@ class TerraspaceBundler::CLI
22
22
  long_desc Help.text("bundle/install")
23
23
  terrafile_option.call
24
24
  def install
25
- Runner.new(options).run
25
+ TB::Runner.new(options).run
26
26
  end
27
27
 
28
28
  desc "purge_cache", "Purge cache."
29
29
  long_desc Help.text("bundle/purge_cache")
30
+ option :yes, aliases: :y, type: :boolean, desc: "bypass are you sure prompt"
30
31
  def purge_cache
31
32
  PurgeCache.new(options).run
32
33
  end
@@ -35,7 +36,8 @@ class TerraspaceBundler::CLI
35
36
  long_desc Help.text("bundle/update")
36
37
  terrafile_option.call
37
38
  def update(*mods)
38
- Runner.new(options.merge(mods: mods, mode: "update")).run
39
+ TB.update_mode = true
40
+ TB::Runner.new(options.merge(mods: mods)).run
39
41
  end
40
42
  end
41
43
  end
@@ -5,4 +5,4 @@
5
5
  sha: bad676a426f5d3ddb48e674bebd6fd52f063a8b4
6
6
  source: org/terraform-random-pet
7
7
  type: git
8
- url: git@github.com:org/terraform-random-pet
8
+ url: https://github.com/org/terraform-random-pet
@@ -2,10 +2,28 @@ class TerraspaceBundler::CLI
2
2
  class PurgeCache < Base
3
3
  include TB::Mod::PathConcern
4
4
  include TB::Util::Logging
5
+ include TB::Util::Sure
5
6
 
6
7
  def run
7
- FileUtils.rm_rf(tmp_root)
8
- logger.info "Removed #{tmp_root}"
8
+ paths = [tmp_root]
9
+ are_you_sure?(paths)
10
+ paths.each do |path|
11
+ FileUtils.rm_rf(path)
12
+ logger.info "Removed #{path}"
13
+ end
14
+
15
+ end
16
+
17
+ def are_you_sure?(paths)
18
+ pretty_paths = paths.map { |p| " #{p}" }.join("\n")
19
+ message = <<~EOL.chomp
20
+ Will remove these folders and all their files:
21
+
22
+ #{pretty_paths}
23
+
24
+ Are you sure?
25
+ EOL
26
+ sure?(message) # from Util::Sure
9
27
  end
10
28
  end
11
29
  end
@@ -5,11 +5,12 @@ module TerraspaceBundler
5
5
 
6
6
  def config
7
7
  config = ActiveSupport::OrderedOptions.new
8
- config.base_clone_url = "git@github.com:"
9
- config.export_path = ENV['TB_EXPORT_PATH'] || "vendor/modules"
8
+ config.base_clone_url = "https://github.com/"
9
+ config.export_to = ENV['TB_EXPORT_TO'] || "vendor/modules"
10
10
  config.export_purge = ENV['TB_EXPORT_PRUNE'] == '0' ? false : true
11
11
  config.lockfile = "#{config.terrafile}.lock"
12
12
  config.logger = new_logger
13
+ config.stack_options = {dest: "app/stacks", purge: nil, examples: "examples"} # Note: Important purge is nil not false so can fallback to Terrafile-level stack_options
13
14
  config.terrafile = ENV['TB_TERRAFILE'] || "Terrafile"
14
15
  config
15
16
  end
@@ -22,5 +22,15 @@ module TerraspaceBundler
22
22
  dsl
23
23
  end
24
24
  memoize :dsl
25
+
26
+ @@update_mode = false
27
+ def update_mode
28
+ @@update_mode
29
+ end
30
+ alias_method :update_mode?, :update_mode
31
+
32
+ def update_mode=(v)
33
+ @@update_mode = v
34
+ end
25
35
  end
26
36
  end
@@ -1,28 +1,32 @@
1
1
  class TerraspaceBundler::Dsl
2
2
  module Syntax
3
3
  def org(url)
4
- global[:org] = url
4
+ config.org = url
5
5
  end
6
6
  alias_method :user, :org
7
7
 
8
8
  def base_clone_url(value)
9
- TB.config.base_clone_url = value
9
+ config.base_clone_url = value
10
10
  end
11
11
 
12
- def export_path(path)
13
- global[:export_path] = path
12
+ def export_to(path)
13
+ config.export_to = path
14
14
  end
15
15
 
16
16
  def export_purge(value)
17
- TB.config.export_purge = value
17
+ config.export_purge = value
18
18
  end
19
19
 
20
- def mod(*args, **options)
21
- meta[:mods] << {args: args, options: options}
20
+ def stack_options(value={})
21
+ config.stack_options.merge!(value)
22
+ end
23
+
24
+ def config
25
+ TB.config
22
26
  end
23
27
 
24
- def global
25
- meta[:global]
28
+ def mod(*args, **options)
29
+ meta[:mods] << {args: args, options: options}
26
30
  end
27
31
  end
28
32
  end
@@ -8,36 +8,42 @@ module TerraspaceBundler
8
8
  end
9
9
 
10
10
  def run
11
- purge
12
- lockfile.mods.each do |mod|
11
+ purge_all
12
+ mods.each do |mod|
13
+ logger.info "Exporting #{mod.name}"
14
+ purge(mod)
13
15
  export(mod)
14
16
  end
15
17
  end
16
18
 
19
+ def mods
20
+ mods = lockfile.mods
21
+ if TB.update_mode? && !@options[:mods].empty?
22
+ mods.select! { |mod| @options[:mods].include?(mod.name) }
23
+ end
24
+ mods
25
+ end
26
+
17
27
  def export(mod)
18
28
  downloader = Mod::Downloader.new(mod)
29
+ downloader.run
19
30
  downloader.switch_version(mod.sha)
20
-
21
- stage_path = stage_path(mod.full_repo)
22
- stage_path = "#{stage_path}/#{mod.subfolder}" if mod.subfolder
23
- mod_path = mod_path(mod)
24
- FileUtils.rm_rf(mod_path)
25
- FileUtils.mkdir_p(File.dirname(mod_path))
26
- FileUtils.cp_r(stage_path, mod_path)
27
- FileUtils.rm_rf("#{mod_path}/.git")
28
- logger.debug "Exported: #{mod_path}"
29
- end
30
-
31
- def mod_path(mod)
32
- name = mod.name
33
- export_to = mod.export_to || TB.config.export_path
34
- "#{export_to}/#{name}"
31
+ copy = Copy.new(mod)
32
+ copy.mod
33
+ copy.stacks
34
+ logger.debug "Exported: #{copy.mod_path}"
35
35
  end
36
36
 
37
37
  private
38
- def purge
38
+ def purge_all
39
+ return if TB.update_mode?
39
40
  return unless TB.config.export_purge
40
- FileUtils.rm_rf(TB.config.export_path)
41
+ FileUtils.rm_rf(TB.config.export_to)
42
+ end
43
+
44
+ def purge(mod)
45
+ mod_path = get_mod_path(mod)
46
+ FileUtils.rm_rf(mod_path)
41
47
  end
42
48
 
43
49
  def lockfile
@@ -0,0 +1,6 @@
1
+ class TerraspaceBundler::Exporter
2
+ class Base
3
+ include TB::Mod::PathConcern
4
+ include TB::Util::Logging
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ class TerraspaceBundler::Exporter
2
+ class Copy < Base
3
+ def initialize(mod)
4
+ @mod = mod
5
+ end
6
+
7
+ def mod
8
+ FileUtils.rm_rf(mod_path)
9
+ FileUtils.mkdir_p(File.dirname(mod_path))
10
+ FileUtils.cp_r(src_path, mod_path)
11
+ FileUtils.rm_rf("#{mod_path}/.git")
12
+ end
13
+
14
+ def stacks
15
+ Stacks.new(@mod).export
16
+ end
17
+
18
+ # src path is from the stage area
19
+ def src_path
20
+ path = stage_path(@mod.full_repo) # from PathConcern
21
+ path = "#{path}/#{@mod.subfolder}" if @mod.subfolder
22
+ path
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ class TerraspaceBundler::Exporter
2
+ class Stacks < Base
3
+ def initialize(mod)
4
+ @mod = mod
5
+ @stacks = mod.stacks || []
6
+ end
7
+
8
+ def export
9
+ @stacks.each do |options|
10
+ Stack.new(@mod, options).export
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ class TerraspaceBundler::Exporter::Stacks
2
+ class Base < TerraspaceBundler::Exporter::Base
3
+ include TB::Util::Logging
4
+ end
5
+ end
@@ -0,0 +1,57 @@
1
+ class TerraspaceBundler::Exporter::Stacks
2
+ class Rewrite < Base
3
+ def initialize(stack)
4
+ @stack = stack
5
+ end
6
+
7
+ def run
8
+ expr = "#{@stack.dest}/*.tf"
9
+ Dir.glob(expr).each do |path|
10
+ next unless File.file?(path) # skip symlinks and dirs
11
+ replace(path)
12
+ end
13
+ end
14
+
15
+ def replace(path)
16
+ lines = IO.readlines(path)
17
+ new_lines = new_lines(lines)
18
+ text = new_lines.join('')
19
+ IO.write(path, text)
20
+ end
21
+
22
+ def new_lines(lines)
23
+ lines.map do |line|
24
+ # leading spaces or no space. but cannot have any other chars
25
+ # can have space betweens source and =
26
+ line =~ /^\s*source\s*=/ ? new_line(line) : line
27
+ end
28
+ end
29
+
30
+ def new_line(line)
31
+ # marker comment so files dont get updated twice when purge is false
32
+ terraspace_comment = "# updated by terraspace"
33
+ return line unless line.include?("../")
34
+ return line if line.include?(terraspace_comment)
35
+
36
+ md = line.match(/^\s*source\s*=\s*"(.*)?"/)
37
+ unless md
38
+ logger.error "ERROR: unable to find the module source".color(:red)
39
+ logger.error line
40
+ exit 1
41
+ end
42
+ # Lots of cases covered by specs
43
+ #
44
+ # ../..
45
+ # ../../
46
+ # ../../modules/iam-user
47
+ # ../../../modules/compute_instance
48
+ #
49
+ source_value = md[1] # IE: ""../../../modules/compute_instance"
50
+ dirs = source_value.split('/')
51
+ count = dirs.count('..')
52
+ mod_dir = dirs[count..-1].join('/')
53
+ full_dir = [@stack.mod.name, mod_dir].reject(&:empty?).join('/')
54
+ %Q| source = "../../modules/#{full_dir}" #{terraspace_comment}\n|
55
+ end
56
+ end
57
+ end