terraspace-bundler 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +72 -24
  4. data/lib/terraspace_bundler.rb +1 -0
  5. data/lib/terraspace_bundler/cli/base.rb +9 -1
  6. data/lib/terraspace_bundler/cli/bundle.rb +26 -12
  7. data/lib/terraspace_bundler/cli/help/bundle/info.md +8 -0
  8. data/lib/terraspace_bundler/cli/help/bundle/install.md +1 -1
  9. data/lib/terraspace_bundler/cli/help/bundle/list.md +9 -0
  10. data/lib/terraspace_bundler/cli/help/bundle/update.md +6 -0
  11. data/lib/terraspace_bundler/cli/{clean.rb → purge_cache.rb} +3 -3
  12. data/lib/terraspace_bundler/cli/{install.rb → runner.rb} +1 -1
  13. data/lib/terraspace_bundler/config.rb +15 -2
  14. data/lib/terraspace_bundler/core.rb +9 -4
  15. data/lib/terraspace_bundler/dsl.rb +6 -3
  16. data/lib/terraspace_bundler/dsl/concern.rb +7 -0
  17. data/lib/terraspace_bundler/dsl/syntax.rb +8 -0
  18. data/lib/terraspace_bundler/exporter.rb +47 -0
  19. data/lib/terraspace_bundler/info.rb +25 -0
  20. data/lib/terraspace_bundler/installer.rb +15 -33
  21. data/lib/terraspace_bundler/list.rb +22 -0
  22. data/lib/terraspace_bundler/lockfile.rb +70 -0
  23. data/lib/terraspace_bundler/lockfile/version_comparer.rb +43 -0
  24. data/lib/terraspace_bundler/lockfile/yamler.rb +37 -0
  25. data/lib/terraspace_bundler/logger.rb +0 -20
  26. data/lib/terraspace_bundler/logger/formatter.rb +7 -0
  27. data/lib/terraspace_bundler/mod.rb +31 -63
  28. data/lib/terraspace_bundler/mod/downloader.rb +55 -0
  29. data/lib/terraspace_bundler/mod/{tmp_paths.rb → path_concern.rb} +1 -1
  30. data/lib/terraspace_bundler/mod/props_builder.rb +57 -0
  31. data/lib/terraspace_bundler/mod/props_extension.rb +15 -0
  32. data/lib/terraspace_bundler/mod/registry.rb +8 -6
  33. data/lib/terraspace_bundler/syncer.rb +62 -4
  34. data/lib/terraspace_bundler/terrafile.rb +39 -0
  35. data/lib/terraspace_bundler/util/git.rb +31 -0
  36. data/lib/terraspace_bundler/{logging.rb → util/logging.rb} +1 -1
  37. data/lib/terraspace_bundler/version.rb +1 -1
  38. data/spec/fixtures/Terrafile +2 -2
  39. data/spec/terraform_bundler/runner_spec.rb +17 -0
  40. metadata +24 -17
  41. data/lib/terraspace_bundler/cli/update.rb +0 -7
  42. data/lib/terraspace_bundler/helper/git.rb +0 -21
  43. data/lib/terraspace_bundler/mod/export.rb +0 -23
  44. data/lib/terraspace_bundler/mod/locked.rb +0 -48
  45. data/lib/terraspace_bundler/mod/sync.rb +0 -53
  46. data/lib/terraspace_bundler/setup.rb +0 -20
  47. data/lib/terraspace_bundler/updater.rb +0 -49
  48. data/lib/terraspace_bundler/updater/lockfile.rb +0 -48
  49. data/lib/terraspace_bundler/util/registry.rb +0 -24
  50. data/spec/terraform_bundler/installer_spec.rb +0 -16
@@ -1,5 +1,5 @@
1
1
  class TerraspaceBundler::Mod
2
- module TmpPaths
2
+ module PathConcern
3
3
  def setup_tmp
4
4
  FileUtils.mkdir_p(cache_root)
5
5
  FileUtils.mkdir_p(stage_root)
@@ -0,0 +1,57 @@
1
+ # Use to build mod from Terrafile entry.
2
+ # The Terrafile.lock does not need this because it's simple and just merges the data.
3
+ class TerraspaceBundler::Mod
4
+ class PropsBuilder
5
+ extend Memoist
6
+ include TerraspaceBundler::Dsl::Concern
7
+
8
+ def initialize(params={})
9
+ @params = params
10
+ @options = params[:options]
11
+ @source, @version = @options[:source], @options[:version]
12
+ end
13
+
14
+ def build
15
+ @options.merge(
16
+ name: name,
17
+ source: source, # overwrite source. @options is a copy though
18
+ type: type,
19
+ url: url,
20
+ )
21
+ end
22
+
23
+ def name
24
+ @params[:args].first
25
+ end
26
+
27
+ def source
28
+ if registry?
29
+ @source
30
+ else
31
+ @source.include?('/') ? @source : "#{dsl.global[:org]}/#{@source}"
32
+ end
33
+ end
34
+
35
+ def url
36
+ if registry?
37
+ registry.github_url
38
+ else
39
+ "#{TB.config.base_clone_url}#{source}" # Note: make sure to not use @source, is org may no be added
40
+ end
41
+ end
42
+
43
+ # IE: git or registry
44
+ def type
45
+ registry? ? "registry" : "git"
46
+ end
47
+
48
+ def registry?
49
+ !@source.nil? && @source.split('/').size == 3
50
+ end
51
+
52
+ def registry
53
+ Registry.new(@source, @version)
54
+ end
55
+ memoize :registry
56
+ end
57
+ end
@@ -0,0 +1,15 @@
1
+ class TerraspaceBundler::Mod
2
+ module PropsExtension
3
+ def props(*names)
4
+ names.each { |n| prop(n) }
5
+ end
6
+
7
+ def prop(name)
8
+ name = name.to_sym
9
+ define_method(name) do
10
+ @props[name]
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -3,8 +3,8 @@ require 'open-uri'
3
3
 
4
4
  class TerraspaceBundler::Mod
5
5
  class Registry
6
- def initialize(mod)
7
- @mod = mod
6
+ def initialize(source, version)
7
+ @source, @version = source, version
8
8
  end
9
9
 
10
10
  # Terrafile example
@@ -25,12 +25,12 @@ class TerraspaceBundler::Mod
25
25
  # https://registry.terraform.io/v1/modules/terraform-aws-modules/sqs/aws/download
26
26
  #
27
27
  # The specific version returns an 204 and then we grab the download url info form the x-terraform-get header.
28
- def to_github
28
+ def github_url
29
29
  base_site = "https://registry.terraform.io"
30
30
  base_url = "#{base_site}/v1/modules"
31
31
 
32
- version = @mod.version.sub(/^v/,'') if @mod.version # v1.0 => 1.0
33
- api_url = [base_url, @mod.source, version, "download"].compact.join('/')
32
+ version = @version.sub(/^v/,'') if @version # v1.0 => 1.0
33
+ api_url = [base_url, @source, version, "download"].compact.join('/')
34
34
  resp = http_request(api_url)
35
35
 
36
36
  case resp.code.to_i
@@ -44,7 +44,9 @@ class TerraspaceBundler::Mod
44
44
  raise "Unable to lookup up module in Terraform Registry: #{resp}"
45
45
  end
46
46
 
47
- download_url.sub(%r{/archive/.*},'')
47
+ url = download_url.sub(%r{/archive/.*},'')
48
+ # IE: git::https://github.com/terraform-aws-modules/terraform-aws-security-group?ref=v3.10.0
49
+ url.sub(/^git::/,'').sub(/\?.*/,'')
48
50
  end
49
51
 
50
52
  private
@@ -1,13 +1,71 @@
1
1
  module TerraspaceBundler
2
2
  class Syncer
3
- def initialize(mods)
4
- @mods = mods
3
+ include TB::Util::Logging
4
+ include Dsl::Concern
5
+
6
+ def initialize(options={})
7
+ @options = options
8
+ @mod_name = @options[:mod]
5
9
  end
6
10
 
7
11
  def run
8
- @mods.each do |mod|
9
- mod.sync
12
+ validate!
13
+ FileUtils.rm_f(TB.config.lockfile) if update_all?
14
+ logger.info "Bundling with #{TB.config.terrafile}..."
15
+ if File.exist?(TB.config.lockfile)
16
+ sync
17
+ else
18
+ create
19
+ end
20
+ TB::Lockfile.write
21
+ end
22
+
23
+ def sync
24
+ sync_mods
25
+ removed_mods = subtract(lockfile.mods, terrafile.mods)
26
+ lockfile.prune(removed_mods)
27
+ end
28
+
29
+ def create
30
+ sync_mods
31
+ end
32
+
33
+ def sync_mods
34
+ terrafile.mods.each do |mod|
35
+ update = update?(mod)
36
+ next unless update
37
+ lockfile.sync(mod) # update (if version mismatch) or create (if missing)
10
38
  end
11
39
  end
40
+
41
+ def update?(mod)
42
+ names = @options[:mods]
43
+ return true if names.nil? || names.empty? # when empty never skip update
44
+ names.include?(mod.name)
45
+ end
46
+
47
+ def validate!
48
+ return unless terrafile.missing_org?
49
+ logger.error "ERROR: org must be set in the #{TB.config.terrafile}.".color(:red)
50
+ logger.error "Please set org in the Terrafile"
51
+ exit 1
52
+ end
53
+
54
+ def update_all?
55
+ @options[:mode] == "update" && @options[:mods].empty?
56
+ end
57
+
58
+ def subtract(mods1, mods2)
59
+ mod2_names = mods2.map(&:name)
60
+ mods1.select {|mod1| !mod2_names.include?(mod1.name) }
61
+ end
62
+
63
+ def terrafile
64
+ Terrafile.instance
65
+ end
66
+
67
+ def lockfile
68
+ Lockfile.instance
69
+ end
12
70
  end
13
71
  end
@@ -0,0 +1,39 @@
1
+ module TerraspaceBundler
2
+ class Terrafile
3
+ include Singleton
4
+ extend Memoist
5
+ include TB::Util::Logging
6
+ include Dsl::Concern
7
+
8
+ # dsl meta example:
9
+ # {:global=>{:org=>"boltopspro"},
10
+ # :mods=>
11
+ # [{:args=>["eks"], :options=>{:source=>"terraform-aws-eks"}},
12
+ # {:args=>["vpc"], :options=>{:source=>"terraform-aws-vpc"}}]}
13
+ def mods
14
+ dsl.meta[:mods].map do |params|
15
+ new_mod(params)
16
+ end
17
+ end
18
+ memoize :mods
19
+
20
+ def new_mod(params)
21
+ props = Mod::PropsBuilder.new(params).build
22
+ Mod.new(props)
23
+ end
24
+
25
+ # Checks if any of the mods defined in Terrafile has an inferred an org
26
+ # In this case the org must be set
27
+ # When a source is set with an inferred org and org is not set it looks like this:
28
+ #
29
+ # dsl.meta has {:source=>"terraform-random-pet"}
30
+ # mod.source is /terraform-random-pet
31
+ #
32
+ # Using info to detect that the org is missing and the Terrafile definition
33
+ # has at least one mod line that has an inferred org.
34
+ #
35
+ def missing_org?
36
+ !!mods.detect { |mod| mod.source.starts_with?('/') }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ module TerraspaceBundler::Util
2
+ module Git
3
+ include TB::Util::Logging
4
+
5
+ def sh(command)
6
+ command = "#{command} 2>&1" # always need output for the sha
7
+ logger.debug "=> #{command}"
8
+ out = `#{command}`
9
+ unless $?.success?
10
+ if command.include?("git")
11
+ raise TB::GitError.new("#{command}\n#{out}")
12
+ else
13
+ logger.error "ERROR: running #{command}".color(:red)
14
+ logger.error out
15
+ exit $?.exitstatus
16
+ end
17
+ end
18
+ out
19
+ end
20
+
21
+ def git(command)
22
+ sh("git #{command}")
23
+ rescue TB::GitError => e
24
+ logger.error "ERROR: There was a git error".color(:red)
25
+ logger.error "Current dir: #{Dir.pwd}"
26
+ logger.error "The error occur when running:"
27
+ logger.error e.message
28
+ exit 1
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
- module TerraspaceBundler
1
+ module TerraspaceBundler::Util
2
2
  module Logging
3
3
  def logger
4
4
  TerraspaceBundler.logger
@@ -1,3 +1,3 @@
1
1
  module TerraspaceBundler
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  org "boltopspro" # set default org
2
2
 
3
3
  # GitHub repo with default org
4
- #mod "elb", source: "terraform-aws-elb", version: "master"
5
- #mod "ec2", source: "terraform-aws-ec2", version: "branch-name"
4
+ # mod "elb", source: "terraform-aws-elb", version: "master"
5
+ # mod "ec2", source: "terraform-aws-ec2", version: "branch-name"
6
6
 
@@ -0,0 +1,17 @@
1
+ describe TB::CLI::Runner do
2
+ let(:runner) { described_class.new }
3
+
4
+ context "runner" do
5
+ # hacky sanity check
6
+ it "run" do
7
+ FileUtils.mkdir_p("tmp")
8
+ FileUtils.rm_f("tmp/Terrafile.lock")
9
+ FileUtils.cp("spec/fixtures/Terrafile", "tmp/Terrafile")
10
+ Dir.chdir("tmp")
11
+ runner.run
12
+ # since no mods are configured
13
+ file_exist = File.exist?("Terrafile.lock")
14
+ expect(file_exist).to be false
15
+ end
16
+ end
17
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terraspace-bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-13 00:00:00.000000000 Z
11
+ date: 2020-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -173,13 +173,15 @@ files:
173
173
  - lib/terraspace_bundler/cli.rb
174
174
  - lib/terraspace_bundler/cli/base.rb
175
175
  - lib/terraspace_bundler/cli/bundle.rb
176
- - lib/terraspace_bundler/cli/clean.rb
177
176
  - lib/terraspace_bundler/cli/help.rb
177
+ - lib/terraspace_bundler/cli/help/bundle/info.md
178
178
  - lib/terraspace_bundler/cli/help/bundle/install.md
179
+ - lib/terraspace_bundler/cli/help/bundle/list.md
180
+ - lib/terraspace_bundler/cli/help/bundle/update.md
179
181
  - lib/terraspace_bundler/cli/help/completion.md
180
182
  - lib/terraspace_bundler/cli/help/completion_script.md
181
- - lib/terraspace_bundler/cli/install.rb
182
- - lib/terraspace_bundler/cli/update.rb
183
+ - lib/terraspace_bundler/cli/purge_cache.rb
184
+ - lib/terraspace_bundler/cli/runner.rb
183
185
  - lib/terraspace_bundler/command.rb
184
186
  - lib/terraspace_bundler/completer.rb
185
187
  - lib/terraspace_bundler/completer/script.rb
@@ -187,26 +189,31 @@ files:
187
189
  - lib/terraspace_bundler/config.rb
188
190
  - lib/terraspace_bundler/core.rb
189
191
  - lib/terraspace_bundler/dsl.rb
192
+ - lib/terraspace_bundler/dsl/concern.rb
190
193
  - lib/terraspace_bundler/dsl/syntax.rb
191
- - lib/terraspace_bundler/helper/git.rb
194
+ - lib/terraspace_bundler/exporter.rb
195
+ - lib/terraspace_bundler/info.rb
192
196
  - lib/terraspace_bundler/installer.rb
197
+ - lib/terraspace_bundler/list.rb
198
+ - lib/terraspace_bundler/lockfile.rb
199
+ - lib/terraspace_bundler/lockfile/version_comparer.rb
200
+ - lib/terraspace_bundler/lockfile/yamler.rb
193
201
  - lib/terraspace_bundler/logger.rb
194
- - lib/terraspace_bundler/logging.rb
202
+ - lib/terraspace_bundler/logger/formatter.rb
195
203
  - lib/terraspace_bundler/mod.rb
196
- - lib/terraspace_bundler/mod/export.rb
197
- - lib/terraspace_bundler/mod/locked.rb
204
+ - lib/terraspace_bundler/mod/downloader.rb
205
+ - lib/terraspace_bundler/mod/path_concern.rb
206
+ - lib/terraspace_bundler/mod/props_builder.rb
207
+ - lib/terraspace_bundler/mod/props_extension.rb
198
208
  - lib/terraspace_bundler/mod/registry.rb
199
- - lib/terraspace_bundler/mod/sync.rb
200
- - lib/terraspace_bundler/mod/tmp_paths.rb
201
- - lib/terraspace_bundler/setup.rb
202
209
  - lib/terraspace_bundler/syncer.rb
203
- - lib/terraspace_bundler/updater.rb
204
- - lib/terraspace_bundler/updater/lockfile.rb
205
- - lib/terraspace_bundler/util/registry.rb
210
+ - lib/terraspace_bundler/terrafile.rb
211
+ - lib/terraspace_bundler/util/git.rb
212
+ - lib/terraspace_bundler/util/logging.rb
206
213
  - lib/terraspace_bundler/version.rb
207
214
  - spec/fixtures/Terrafile
208
215
  - spec/spec_helper.rb
209
- - spec/terraform_bundler/installer_spec.rb
216
+ - spec/terraform_bundler/runner_spec.rb
210
217
  - terraspace-bundler.gemspec
211
218
  homepage: https://github.com/boltops-tools/terraspace-bundler
212
219
  licenses:
@@ -234,4 +241,4 @@ summary: Bundles terraform modules
234
241
  test_files:
235
242
  - spec/fixtures/Terrafile
236
243
  - spec/spec_helper.rb
237
- - spec/terraform_bundler/installer_spec.rb
244
+ - spec/terraform_bundler/runner_spec.rb
@@ -1,7 +0,0 @@
1
- class TerraspaceBundler::CLI
2
- class Update < Base
3
- def run
4
- TB::Updater.new(@options).run
5
- end
6
- end
7
- end
@@ -1,21 +0,0 @@
1
- module TerraspaceBundler::Helper
2
- module Git
3
- include TB::Logging
4
-
5
- def sh(command)
6
- command = "#{command} 2>&1" # always need output for the sha
7
- logger.debug "=> #{command}"
8
- out = `#{command}`
9
- unless $?.success?
10
- logger.error "ERROR: running #{command}"
11
- logger.error out
12
- exit $?.exitstatus
13
- end
14
- out
15
- end
16
-
17
- def git(command)
18
- sh("git #{command}")
19
- end
20
- end
21
- end
@@ -1,23 +0,0 @@
1
- class TerraspaceBundler::Mod
2
- class Export
3
- include TmpPaths
4
-
5
- def initialize(locked_mod)
6
- @locked_mod = locked_mod
7
- end
8
-
9
- def run
10
- stage_path = stage_path(@locked_mod.full_repo)
11
- stage_path = "#{stage_path}/#{@locked_mod.path}" if @locked_mod.path
12
- export_path = export_path(@locked_mod.name)
13
- FileUtils.rm_rf(export_path)
14
- FileUtils.mkdir_p(File.dirname(export_path))
15
- FileUtils.cp_r(stage_path, export_path)
16
- FileUtils.rm_rf("#{export_path}/.git")
17
- end
18
-
19
- def export_path(repo)
20
- "#{TB.config.export_path}/#{repo}"
21
- end
22
- end
23
- end