terradactyl-terraform 0.13.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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