terradactyl-terraform 0.13.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4027e42749bc30e77a4601aae086542e62d4ed9c50913a480d7ff6bc7973c5a5
4
- data.tar.gz: d5ab49216b9e1e7bbf34b213026e6ef4c851c74f3c03ac830ab11fd62419f3af
3
+ metadata.gz: 0fc3e3e607f1fe5c8707723fbf1683eee4dc260b010602ab210dc1db5f651f15
4
+ data.tar.gz: 0ad839a9f247a9ff0a99123566c61e66719a20a67ce2fc75f211ceaa652f9dc7
5
5
  SHA512:
6
- metadata.gz: 3ecd70785e909819604b60023ed3dc71eaecd3c852dbcd404b0e6d8c93d962c83256f8b9f57706dd6a9b1c3b3a2dbb95b7d994ca18da33a7db4276a6c62bc9b4
7
- data.tar.gz: 6183727083d3e6284574669732d01532b9b36fbadfc6fcea700b9a788c3e84875c9d035cc88dd6c8fc13c88bdfea36cd4b02da243dc47e30f5cd1f7936d8bbfa
6
+ metadata.gz: 97ef85fc1987b64db1a7976ed2e26f8b91c48ed35645585702bc64f51b5a512f82cddb680516ee66f6101dd9d86abb8a1fbafa6948d5d778cacc4a4031e4f1f9
7
+ data.tar.gz: 65658df7e0e1db4f4538367555fdcc61f137c5a287b1cb3e8479c78e48619388e045550f4af6b65ff073126d156abe0189cbb741488cf42efee2d75eb231b8a3
@@ -7,6 +7,9 @@ on:
7
7
  paths:
8
8
  - lib/terradactyl/terraform/version.rb
9
9
 
10
+ # Using the Ruby teams https://github.com/ruby/setup-ruby, not the Github
11
+ # team's https://github.com/actions/setup-ruby
12
+
10
13
  jobs:
11
14
  release:
12
15
  env:
@@ -20,7 +23,7 @@ jobs:
20
23
  - name: Checkout Code
21
24
  uses: actions/checkout@v2
22
25
  - name: Setup Ruby
23
- uses: actions/setup-ruby@v1
26
+ uses: ruby/setup-ruby@v1
24
27
  with:
25
28
  ruby-version: '2.7'
26
29
  bundler-cache: true
@@ -39,7 +42,7 @@ jobs:
39
42
  with:
40
43
  tag_name: v${{ env.RELEASE_VERSION }}
41
44
  release_name: v${{ env.RELEASE_VERSION }}
42
- body: ${{ env.RELEASE_BODY }}
45
+ body_path: ${{ env.RELEASE_BODY_PATH }}
43
46
  draft: false
44
47
  prerelease: false
45
48
  - name: Upload Asset
@@ -0,0 +1,26 @@
1
+ name: Build Status
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ # Using the Ruby teams https://github.com/ruby/setup-ruby, not the Github
9
+ # team's https://github.com/actions/setup-ruby
10
+
11
+ jobs:
12
+ validate:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Git clone
16
+ uses: actions/checkout@v2
17
+ with:
18
+ fetch-depth: 2
19
+ - name: Setup Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: '2.7'
23
+ bundler-cache: true
24
+ - name: Run tests
25
+ id: test
26
+ run: bundle exec rake spec
@@ -5,6 +5,9 @@ on:
5
5
  paths:
6
6
  - '**.rb'
7
7
 
8
+ # Using the Ruby teams https://github.com/ruby/setup-ruby, not the Github
9
+ # team's https://github.com/actions/setup-ruby
10
+
8
11
  jobs:
9
12
  validate:
10
13
  runs-on: ubuntu-latest
@@ -14,15 +17,13 @@ jobs:
14
17
  with:
15
18
  fetch-depth: 2
16
19
  - name: Setup Ruby
17
- uses: actions/setup-ruby@v1
20
+ uses: ruby/setup-ruby@v1
18
21
  with:
19
22
  ruby-version: '2.7'
20
23
  bundler-cache: true
21
- - name: Bundle install
22
- run: |
23
- bundle config path vendor/bundle
24
- bundle install --jobs 4 --retry 3
25
24
  - name: Run lint
25
+ id: lint
26
26
  run: bundle exec rake lint
27
27
  - name: Run tests
28
+ id: test
28
29
  run: bundle exec rake spec
data/.gitignore CHANGED
@@ -11,3 +11,7 @@ vendor
11
11
 
12
12
  # rspec failure tracking
13
13
  .rspec_status
14
+
15
+ # terraform artifacts
16
+ *.tfout
17
+ .terraform
data/.rubocop.yml CHANGED
@@ -10,6 +10,8 @@ Metrics/CyclomaticComplexity:
10
10
  Max: 10
11
11
  Metrics/ClassLength:
12
12
  Max: 115
13
+ Naming/ClassAndModuleCamelCase:
14
+ Enabled: false
13
15
  Naming/UncommunicativeMethodParamName:
14
16
  MinNameLength: 2
15
17
  Style/IfUnlessModifier:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.1.2 (2022-01-03)
4
+
5
+ BUG FIXES:
6
+
7
+ * fix calculation of latest version
8
+ * fix failing tests
9
+
10
+ ## 1.1.0 (2021-12-09)
11
+
12
+ NEW FEATURES:
13
+
14
+ * add support for Terraform version `~> 1.1.0`
15
+ * Update lib/terradactyl/terraform/commands/destroy.rb (add Rev1_01)
16
+ * Update lib/terradactyl/terraform/commands/init.rb (add Rev1_01)
17
+ * Update spec/fixtures/stacks (add rev1_01)
18
+ * Update spec/helpers.rb (add rev1_01 and lock rev1_00 to 1.0.11)
19
+
20
+ ## 1.0.0 (2021-06-09)
21
+
22
+ NEW FEATURES:
23
+
24
+ * add support for Terraform version `~> 1.0.0`
25
+
26
+ BUG FIXES:
27
+
28
+ * fix broken version revision resolution
29
+
30
+ ## 0.15.0 (2021-04-27)
31
+
32
+ NEW FEATURES:
33
+
34
+ * adds support for Terraform version `0.14.x`
35
+ * adds support for Terraform version `0.15.x`
36
+
37
+ BUG FIXES:
38
+
39
+ * fix broken version expression resolution
40
+
3
41
  ## 0.13.0 (2020-11-23)
4
42
 
5
43
  NEW FEATURES:
data/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # Terradactyl::Terraform
2
2
 
3
- A collection of libraries for executing Terraform CLI operations, managing Terraform binary versions, and other related tasks.
3
+ [![Gem Version](https://badge.fury.io/rb/terradactyl-terraform.svg)](https://badge.fury.io/rb/terradactyl-terraform)
4
+ ![Build Status](https://github.com/vcilabs/terradactyl-terraform/workflows/Build%20Status/badge.svg)
5
+
6
+ Library for executing Terraform CLI operations, managing Terraform binary versions, and other related tasks.
4
7
 
5
8
  ## Requirements
6
9
 
7
10
  Requires Ruby 2.5 or greater.
8
11
 
9
- NOTE: While `VersionManager` can fetch & install ANY available version of Terraform, the Terraform sub-command operations are only supported between stable versions `~> 0.11.x` and `~> 0.13.x`.
12
+ NOTE: While `VersionManager` can fetch & install ANY available version of Terraform, the Terraform sub-command operations are only supported between stable versions `~> 0.11.x` and `~> 0.15.x`.
10
13
 
11
14
  ## Installation
12
15
 
@@ -32,7 +35,7 @@ If you wish to try out some features, launch a `pry` repl and poke around ...
32
35
 
33
36
  $ bundle exec pry -r 'terradactyl/terraform'
34
37
  [1] pry(main)> Terradactyl::Terraform::VERSION
35
- => "0.13.0"
38
+ => "0.15.0"
36
39
 
37
40
  ### Managing different Terraform versions
38
41
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Apply
7
7
  def defaults
8
8
  {
@@ -31,12 +31,6 @@ module Terradactyl
31
31
  end
32
32
  end
33
33
 
34
- module Rev012
35
- module Apply
36
- include Rev011::Apply
37
- end
38
- end
39
-
40
34
  module Commands
41
35
  class Apply < Base
42
36
  end
@@ -3,20 +3,31 @@
3
3
  module Terradactyl
4
4
  module Terraform
5
5
  class << self
6
+ def calc_revision(version)
7
+ major, minor = version.split(/\.|-/).take(2)
8
+ major = major.to_i.zero? ? major : major + '_'
9
+ minor = minor.rjust(2, '0') # pad a single digit
10
+ ['Rev', major, minor].join
11
+ end
12
+
6
13
  def revision(version)
7
- version ? ['Rev', *version.split(/\.|-/).take(2)].join : revisions.last
14
+ version ? calc_revision(version) : revisions.last
8
15
  end
9
16
 
10
17
  def revisions
11
- contstants.select { |c| c =~ /Rev/ }.sort
18
+ constants.select { |c| c =~ /Rev/ }.sort
12
19
  end
13
20
 
14
21
  def select_revision(version, object)
15
22
  klass_name = object.class.name.split('::').last
16
- const_name = "#{revision(version)}::#{klass_name}"
23
+ revision = "#{revision(version)}::#{klass_name}"
17
24
  return if klass_name == 'Base'
18
25
 
19
- object.extend(Terradactyl::Terraform.const_get(const_name))
26
+ if Terradactyl::Terraform.const_defined?(revision)
27
+ object.extend(Terradactyl::Terraform.const_get(revision))
28
+ else
29
+ object.extend(Terradactyl::Terraform.const_get("Subcommands::#{klass_name}"))
30
+ end
20
31
  end
21
32
  end
22
33
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Destroy
7
7
  def defaults
8
8
  {
@@ -32,9 +32,33 @@ module Terradactyl
32
32
  end
33
33
  end
34
34
 
35
- module Rev012
35
+ module Rev015
36
36
  module Destroy
37
- include Rev011::Destroy
37
+ include Terradactyl::Terraform::Subcommands::Destroy
38
+
39
+ def defaults
40
+ super.reject { |k, _v| k == 'force' }
41
+ end
42
+
43
+ def switches
44
+ super.reject { |e| e == 'force' }
45
+ end
46
+
47
+ def arguments
48
+ super.reject { |k, _v| k == 'force' }
49
+ end
50
+ end
51
+ end
52
+
53
+ module Rev1_00
54
+ module Destroy
55
+ include Terradactyl::Terraform::Rev015::Destroy
56
+ end
57
+ end
58
+
59
+ module Rev1_01
60
+ module Destroy
61
+ include Terradactyl::Terraform::Rev015::Destroy
38
62
  end
39
63
  end
40
64
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Fmt
7
7
  def defaults
8
8
  {
@@ -19,12 +19,6 @@ module Terradactyl
19
19
  end
20
20
  end
21
21
 
22
- module Rev012
23
- module Fmt
24
- include Rev011::Fmt
25
- end
26
- end
27
-
28
22
  module Commands
29
23
  class Fmt < Base
30
24
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Init
7
7
  def defaults
8
8
  {
@@ -33,9 +33,29 @@ module Terradactyl
33
33
  end
34
34
  end
35
35
 
36
- module Rev012
36
+ module Rev015
37
37
  module Init
38
- include Rev011::Init
38
+ include Terradactyl::Terraform::Subcommands::Init
39
+
40
+ def defaults
41
+ super.reject { |k, _v| k == 'lock' }
42
+ end
43
+
44
+ def arguments
45
+ super.reject { |k, _v| k == 'lock' }
46
+ end
47
+ end
48
+ end
49
+
50
+ module Rev1_00
51
+ module Init
52
+ include Terradactyl::Terraform::Rev015::Init
53
+ end
54
+ end
55
+
56
+ module Rev1_01
57
+ module Init
58
+ include Terradactyl::Terraform::Rev015::Init
39
59
  end
40
60
  end
41
61
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Plan
7
7
  def defaults
8
8
  {
@@ -33,12 +33,6 @@ module Terradactyl
33
33
  end
34
34
  end
35
35
 
36
- module Rev012
37
- module Plan
38
- include Rev011::Plan
39
- end
40
- end
41
-
42
36
  module Commands
43
37
  class Plan < Base
44
38
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Refresh
7
7
  def defaults
8
8
  {
@@ -27,12 +27,6 @@ module Terradactyl
27
27
  end
28
28
  end
29
29
 
30
- module Rev012
31
- module Refresh
32
- include Rev011::Refresh
33
- end
34
- end
35
-
36
30
  module Commands
37
31
  class Refresh < Base
38
32
  end
@@ -2,35 +2,37 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Show
7
7
  def defaults
8
8
  {
9
- 'module-depth' => -1,
9
+ 'json' => false,
10
10
  'no-color' => false
11
11
  }
12
12
  end
13
13
 
14
14
  def switches
15
15
  %w[
16
+ json
16
17
  no-color
17
18
  ]
18
19
  end
19
20
  end
20
21
  end
21
22
 
22
- module Rev012
23
+ module Rev011
24
+ include Terradactyl::Terraform::Subcommands::Show
25
+
23
26
  module Show
24
27
  def defaults
25
28
  {
26
- 'json' => false,
29
+ 'module-depth' => -1,
27
30
  'no-color' => false
28
31
  }
29
32
  end
30
33
 
31
34
  def switches
32
35
  %w[
33
- json
34
36
  no-color
35
37
  ]
36
38
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Validate
7
7
  def defaults
8
8
  {
@@ -2,17 +2,11 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- module Rev011
5
+ module Subcommands
6
6
  module Version
7
7
  end
8
8
  end
9
9
 
10
- module Rev012
11
- module Version
12
- include Rev011::Version
13
- end
14
- end
15
-
16
10
  module Commands
17
11
  class Version < Base
18
12
  end
@@ -11,10 +11,3 @@ require_relative 'commands/destroy'
11
11
  require_relative 'commands/fmt'
12
12
  require_relative 'commands/show'
13
13
  require_relative 'commands/validate'
14
- require_relative 'commands/checklist'
15
-
16
- module Terradactyl
17
- module Terraform
18
- Rev013 = Rev012
19
- end
20
- end
@@ -8,6 +8,8 @@ module Terradactyl
8
8
  class PlanFileParser
9
9
  attr_reader :plan_path
10
10
 
11
+ PLAN_FILE_SIGNATURE = 'Terraform will perform the following actions'
12
+
11
13
  def self.load(plan_path)
12
14
  new(plan_path)
13
15
  end
@@ -24,10 +26,19 @@ module Terradactyl
24
26
  @data ||= parse(@plan_path)
25
27
  end
26
28
 
29
+ def signature
30
+ self.class::PLAN_FILE_SIGNATURE
31
+ end
32
+
27
33
  private
28
34
 
35
+ # rubocop:disable Metrics/AbcSize
29
36
  def parse(plan_path)
30
- captured = Commands::Show.execute(dir_or_plan: plan_path,
37
+ file_name = File.basename(plan_path)
38
+ stack_name = File.dirname(plan_path)
39
+ pushd(stack_name)
40
+
41
+ captured = Commands::Show.execute(dir_or_plan: file_name,
31
42
  options: options,
32
43
  capture: true)
33
44
 
@@ -40,7 +51,7 @@ module Terradactyl
40
51
  parsed = JSON.parse(captured.stdout)
41
52
 
42
53
  # The the `prior_state` node in the JSON returned from the
43
- # planfile is not assembled consitently and therefore, never obeys
54
+ # planfile is not assembled consistently and therefore, never obeys
44
55
  # any sort order. It does not appear to be of any consequence when
45
56
  # calculating a checksum for the plan, so we excise it in an effort
46
57
  # to conform the data. This is sub-optimal, but presently necessary.
@@ -48,7 +59,10 @@ module Terradactyl
48
59
  # brian.warsing@visioncritical.com (2020-06-18)
49
60
 
50
61
  parsed.reject { |k| k == 'prior_state' }.to_json
62
+ ensure
63
+ popd
51
64
  end
65
+ # rubocop:enable Metrics/AbcSize
52
66
 
53
67
  def options
54
68
  Commands::Options.new do |opts|
@@ -57,6 +71,40 @@ module Terradactyl
57
71
  opts.json = true
58
72
  end
59
73
  end
74
+
75
+ def pushd(path)
76
+ @working_dir_last = Dir.pwd
77
+ Dir.chdir(path)
78
+ end
79
+
80
+ def popd
81
+ Dir.chdir(@working_dir_last)
82
+ end
83
+ end
84
+ end
85
+
86
+ module Rev013
87
+ class PlanFileParser < Rev012::PlanFileParser
88
+ end
89
+ end
90
+
91
+ module Rev014
92
+ class PlanFileParser < Rev012::PlanFileParser
93
+ end
94
+ end
95
+
96
+ module Rev015
97
+ class PlanFileParser < Rev012::PlanFileParser
98
+ end
99
+ end
100
+
101
+ module Rev1_00
102
+ class PlanFileParser < Rev012::PlanFileParser
103
+ end
104
+ end
105
+
106
+ module Rev1_01
107
+ class PlanFileParser < Rev012::PlanFileParser
60
108
  end
61
109
  end
62
110
 
@@ -120,20 +168,18 @@ module Terradactyl
120
168
  end
121
169
  # rubocop:enable Security/MarshalLoad
122
170
 
123
- attr_reader :data, :checksum, :file_name, :stack_name
124
- attr_writer :plan_output
171
+ attr_reader :data, :checksum, :file_name, :stack_name, :parser
172
+ attr_writer :plan_output, :error_output
125
173
  attr_accessor :base_folder
126
174
 
127
175
  WARN_NO_PLAN_OUTPUT = 'WARN: no plan output is available'
128
176
 
129
177
  def initialize(plan_path:, parser:)
130
178
  @plan_path = plan_path.to_s
131
- @parser = parser
132
179
  @file_name = File.basename(@plan_path)
133
180
  @stack_name = File.basename(@plan_path, '.tfout')
134
181
  @base_folder = File.dirname(@plan_path).split('/')[-2]
135
-
136
- parse(@plan_path)
182
+ @parser = parse(parser, @plan_path)
137
183
  end
138
184
 
139
185
  def save(artifact_path: artifact)
@@ -150,7 +196,11 @@ module Terradactyl
150
196
  end
151
197
 
152
198
  def plan_output
153
- format_output(@plan_output)
199
+ format_plan_output(@plan_output)
200
+ end
201
+
202
+ def error_output
203
+ format_error_output(@error_output)
154
204
  end
155
205
 
156
206
  def to_markdown
@@ -172,8 +222,8 @@ module Terradactyl
172
222
 
173
223
  private
174
224
 
175
- def parse(plan_path)
176
- @parser.load(plan_path).tap do |dat|
225
+ def parse(parser, plan_path)
226
+ parser.load(plan_path).tap do |dat|
177
227
  @data = dat.data
178
228
  @checksum = dat.checksum
179
229
  end
@@ -186,17 +236,18 @@ module Terradactyl
186
236
  'terradactyl.planfile.data')
187
237
  end
188
238
 
189
- def format_output(string)
239
+ def format_error_output(string)
240
+ string.strip
241
+ end
242
+
243
+ def format_plan_output(string)
190
244
  return WARN_NO_PLAN_OUTPUT unless string
191
245
 
192
- delimit = '-' * 72
246
+ # These hypens are different!
247
+ delimit = /(?:─|-){72,77}/
193
248
  content = string.split(delimit).compact.reject(&:empty?)
194
249
 
195
- if content.size == 2
196
- content.last.strip
197
- else
198
- content[content.size / 3].strip
199
- end
250
+ content.select { |e| e =~ /#{parser.signature}/ }.first.strip
200
251
  end
201
252
  end
202
253
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Terradactyl
4
4
  module Terraform
5
- VERSION = '0.13.0'
5
+ VERSION = '1.1.2'
6
6
  end
7
7
  end
@@ -4,16 +4,15 @@ module Terradactyl
4
4
  module Terraform
5
5
  module VersionManager
6
6
  class Defaults
7
- DEFAULT_INSTALL_DIR = Gem.bindir
8
- DEFAULT_DOWNLOADS_URL = 'https://www.terraform.io/downloads.html'
9
- DEFAULT_RELEASES_URL = 'https://releases.hashicorp.com/terraform'
10
- DEFAULT_VERSION = nil
7
+ DEFAULT_INSTALL_DIR = Gem.bindir
8
+ DEFAULT_RELEASES_URL = 'https://releases.hashicorp.com/terraform'
9
+ DEFAULT_VERSION = nil
11
10
 
12
11
  def self.load
13
12
  new
14
13
  end
15
14
 
16
- attr_reader :version, :install_dir, :downloads_url, :releases_url
15
+ attr_reader :version, :install_dir, :releases_url
17
16
 
18
17
  def initialize
19
18
  load_defaults
@@ -31,10 +30,6 @@ module Terradactyl
31
30
  @install_dir = validate_path(option) || DEFAULT_INSTALL_DIR
32
31
  end
33
32
 
34
- def downloads_url=(option)
35
- @downloads_url = validate_url(option) || DEFAULT_DOWNLOADS_URL
36
- end
37
-
38
33
  def releases_url=(option)
39
34
  @releases_url = validate_url(option) || DEFAULT_RELEASES_URL
40
35
  end
@@ -66,7 +61,6 @@ module Terradactyl
66
61
 
67
62
  def load_defaults
68
63
  @install_dir = DEFAULT_INSTALL_DIR
69
- @downloads_url = DEFAULT_DOWNLOADS_URL
70
64
  @releases_url = DEFAULT_RELEASES_URL
71
65
  @version = DEFAULT_VERSION
72
66
  end
@@ -36,10 +36,6 @@ module Terradactyl
36
36
  end
37
37
  end
38
38
 
39
- def downloads_url
40
- VersionManager.downloads_url
41
- end
42
-
43
39
  def releases_url
44
40
  VersionManager.releases_url
45
41
  end
@@ -8,6 +8,7 @@ require_relative 'version_manager/binary'
8
8
 
9
9
  module Terradactyl
10
10
  module Terraform
11
+ # rubocop:disable Metrics/ModuleLength
11
12
  module VersionManager
12
13
  class VersionManagerError < RuntimeError
13
14
  def initialize(msg)
@@ -17,8 +18,10 @@ module Terradactyl
17
18
 
18
19
  ERROR_MISSING = 'Terraform not installed'
19
20
  ERROR_INVALID_VERSION_STRING = 'Invalid version string'
21
+ ERROR_UNRESOLVABLE_VERSION = 'Unresolvable version string'
22
+ ERROR_UNPARSEABLE_VERSION = 'Unparsable version string'
20
23
  SEMVER_EXP_RE = /
21
- ^\s*((?<op>(<=|>=|>|<|~>))\s+)?
24
+ ^\s*((?<op>(=|<=|>=|>|<|~>))\s+)?
22
25
  (?<semver>\d+(\.\d+)?(\.\d+)?(-\w+)?)
23
26
  /x.freeze
24
27
 
@@ -28,8 +31,7 @@ module Terradactyl
28
31
  class << self
29
32
  extend Forwardable
30
33
 
31
- def_delegators :@options, :version, :version=, :install_dir,
32
- :install_dir=, :downloads_url, :downloads_url=,
34
+ def_delegators :@options, :version, :version=, :install_dir, :install_dir=,
33
35
  :releases_url, :releases_url=, :reset!
34
36
 
35
37
  def_delegators :@inventory, :[], :binaries, :any?
@@ -78,12 +80,8 @@ module Terradactyl
78
80
  end
79
81
 
80
82
  def resolve(expression)
81
- data = expression.to_s.match(SEMVER_EXP_RE) || {}
82
- op = data['op']
83
- semver = data['semver']
84
-
85
- unless (resolution = resolve_expression(op, semver))
86
- raise VersionManagerError, ERROR_INVALID_VERSION_STRING
83
+ unless (resolution = resolve_expression(expression.to_s.strip))
84
+ raise VersionManagerError, ERROR_UNRESOLVABLE_VERSION
87
85
  end
88
86
 
89
87
  resolution
@@ -91,23 +89,72 @@ module Terradactyl
91
89
 
92
90
  private
93
91
 
94
- def resolve_expression(op, semver)
95
- case op
96
- when /~>/
97
- min = semver
98
- max = pessimistic_max(semver)
99
- versions(local: false).select { |v| (v >= min && v < max) }.last
100
- when />=|>|<=|</
101
- versions(local: false).select { |v| v.send(op.to_sym, semver) }.last
92
+ def resolve_expression(expression)
93
+ candiates = case expression
94
+ when /^~>/
95
+ resolve_pessimistic(expression)
96
+ when /^(?:>=|>|<=|<)/
97
+ resolve_range(expression)
98
+ when /^(?:=\s+)?\d+\.\d+\.\d+(?:-.*)?/
99
+ return resolve_equality(expression)
100
+ else
101
+ raise VersionManagerError, ERROR_INVALID_VERSION_STRING
102
+ end
103
+
104
+ candiates.reject { |v| v =~ /-/ }.last
105
+ end
106
+
107
+ def resolve_equality(expression)
108
+ expression.split(/\s+/).last
109
+ end
110
+
111
+ # rubocop:disable Metrics/AbcSize
112
+ def resolve_range(expression)
113
+ left, right = expression.split(/\s*,\s*/)
114
+ l_op, l_semver = parse_expression(left).captures
115
+
116
+ if right
117
+ r_op, r_semver = parse_expression(right).captures
102
118
  else
103
- versions(local: false).delete(semver)
119
+ r_op = l_op
120
+ r_semver = l_semver
121
+ end
122
+
123
+ l_gemver = Gem::Version.new(l_semver)
124
+ r_gemver = Gem::Version.new(r_semver)
125
+
126
+ versions(local: false).select do |v|
127
+ v = Gem::Version.new(v)
128
+ (v.send(l_op.to_sym, l_gemver) && v.send(r_op.to_sym, r_gemver))
129
+ end
130
+ end
131
+ # rubocop:enable Metrics/AbcSize
132
+
133
+ def resolve_pessimistic(expression)
134
+ semver = parse_expression(expression).captures.last
135
+ min = Gem::Version.new(semver)
136
+ max = Gem::Version.new(pessimistic_max(semver))
137
+
138
+ versions(local: false).select do |v|
139
+ v = Gem::Version.new(v)
140
+ (v >= min && v < max)
104
141
  end
105
142
  end
106
143
 
144
+ def parse_expression(expression)
145
+ match = expression.to_s.match(SEMVER_EXP_RE)
146
+ raise VersionManagerError, ERROR_UNPARSEABLE_VERSION unless match
147
+
148
+ match
149
+ end
150
+
107
151
  def remote_versions
108
152
  fh = Downloader.fetch(releases_url)
109
153
  re = /terraform_(?<version>\d+\.\d+\.\d+(-\w+)?)/
110
154
  fh.read.scan(re).flatten.sort_by { |v| Gem::Version.new(v) }
155
+ ensure
156
+ fh.close
157
+ fh.unlink
111
158
  end
112
159
 
113
160
  def pessimistic_max(version)
@@ -118,14 +165,10 @@ module Terradactyl
118
165
  end
119
166
 
120
167
  def calculate_latest
121
- fh = Downloader.fetch(downloads_url)
122
- re = %r{#{releases_url}\/(?<version>\d+\.\d+\.\d+)}
123
- fh.read.match(re)['version']
124
- ensure
125
- fh.close
126
- fh.unlink
168
+ remote_versions.reject { |e| e =~ /\d+\.\d+\.\d+-/ }.last
127
169
  end
128
170
  end
129
171
  end
172
+ # rubocop:enable Metrics/ModuleLength
130
173
  end
131
174
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terradactyl-terraform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Warsing
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-24 00:00:00.000000000 Z
11
+ date: 2022-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -146,6 +146,7 @@ extensions: []
146
146
  extra_rdoc_files: []
147
147
  files:
148
148
  - ".github/workflows/build-and-release.yml"
149
+ - ".github/workflows/build-status.yml"
149
150
  - ".github/workflows/validate-pullrequest.yml"
150
151
  - ".gitignore"
151
152
  - ".rubocop.yml"
@@ -158,7 +159,6 @@ files:
158
159
  - lib/terradactyl/terraform/commands.rb
159
160
  - lib/terradactyl/terraform/commands/apply.rb
160
161
  - lib/terradactyl/terraform/commands/base.rb
161
- - lib/terradactyl/terraform/commands/checklist.rb
162
162
  - lib/terradactyl/terraform/commands/destroy.rb
163
163
  - lib/terradactyl/terraform/commands/fmt.rb
164
164
  - lib/terradactyl/terraform/commands/init.rb
@@ -196,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
196
  - !ruby/object:Gem::Version
197
197
  version: '0'
198
198
  requirements: []
199
- rubygems_version: 3.1.4
199
+ rubygems_version: 3.1.6
200
200
  signing_key:
201
201
  specification_version: 4
202
202
  summary: Core functionality for managing a Terraform repo
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Terradactyl
4
- module Terraform
5
- module Rev011
6
- module Checklist
7
- def defaults
8
- {}
9
- end
10
-
11
- def switches
12
- []
13
- end
14
-
15
- def subcmd
16
- '0.12checklist'
17
- end
18
- end
19
- end
20
-
21
- module Rev012
22
- module Checklist
23
- include Rev011::Checklist
24
- end
25
- end
26
-
27
- module Commands
28
- class Checklist < Base
29
- end
30
- end
31
- end
32
- end