ruby-terraform 0.65.0.pre.10 → 0.65.0.pre.15

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +18 -10
  3. data/README.md +2 -19
  4. data/lib/ruby_terraform.rb +691 -18
  5. data/lib/ruby_terraform/commands/apply.rb +75 -1
  6. data/lib/ruby_terraform/commands/base.rb +18 -15
  7. data/lib/ruby_terraform/commands/destroy.rb +67 -1
  8. data/lib/ruby_terraform/commands/force_unlock.rb +28 -0
  9. data/lib/ruby_terraform/commands/format.rb +39 -0
  10. data/lib/ruby_terraform/commands/get.rb +31 -0
  11. data/lib/ruby_terraform/commands/graph.rb +38 -0
  12. data/lib/ruby_terraform/commands/import.rb +95 -1
  13. data/lib/ruby_terraform/commands/init.rb +72 -1
  14. data/lib/ruby_terraform/commands/login.rb +24 -0
  15. data/lib/ruby_terraform/commands/logout.rb +21 -0
  16. data/lib/ruby_terraform/commands/output.rb +34 -4
  17. data/lib/ruby_terraform/commands/plan.rb +67 -1
  18. data/lib/ruby_terraform/commands/providers.rb +22 -0
  19. data/lib/ruby_terraform/commands/providers_lock.rb +66 -0
  20. data/lib/ruby_terraform/commands/providers_mirror.rb +42 -0
  21. data/lib/ruby_terraform/commands/taint.rb +2 -1
  22. data/lib/ruby_terraform/options.rb +25 -3
  23. data/lib/ruby_terraform/options/common.rb +1 -0
  24. data/lib/ruby_terraform/options/definition.rb +172 -0
  25. data/lib/ruby_terraform/options/definitions.rb +103 -0
  26. data/lib/ruby_terraform/options/factory.rb +10 -102
  27. data/lib/ruby_terraform/options/name.rb +11 -19
  28. data/lib/ruby_terraform/options/types.rb +27 -0
  29. data/lib/ruby_terraform/options/types/base.rb +6 -13
  30. data/lib/ruby_terraform/options/types/flag.rb +1 -3
  31. data/lib/ruby_terraform/options/types/standard.rb +1 -27
  32. data/lib/ruby_terraform/options/values.rb +38 -0
  33. data/lib/ruby_terraform/options/values/base.rb +15 -0
  34. data/lib/ruby_terraform/options/values/boolean.rb +13 -11
  35. data/lib/ruby_terraform/options/values/complex.rb +19 -0
  36. data/lib/ruby_terraform/options/values/key_value.rb +21 -0
  37. data/lib/ruby_terraform/options/values/string.rb +17 -0
  38. data/lib/ruby_terraform/version.rb +1 -1
  39. data/ruby_terraform.gemspec +3 -1
  40. metadata +40 -5
  41. data/lib/ruby_terraform/options/types/boolean.rb +0 -18
@@ -5,12 +5,34 @@ require_relative '../options/common'
5
5
 
6
6
  module RubyTerraform
7
7
  module Commands
8
+ # Wraps the +terraform providers+ command which prints out a tree of modules
9
+ # in the referenced configuration annotated with their provider
10
+ # requirements.
11
+ #
12
+ # This provides an overview of all of the provider requirements across all
13
+ # referenced modules, as an aid to understanding why particular provider
14
+ # plugins are needed and why particular versions are selected.
15
+ #
16
+ # For options accepted on construction, see {#initialize}.
17
+ #
18
+ # When executing an instance of {Plan} via {#execute}, the following
19
+ # options are supported:
20
+ #
21
+ # * +:chdir+: the path of a working directory to switch to before executing
22
+ # the given subcommand.
23
+ #
24
+ # @example Basic Invocation
25
+ # RubyTerraform::Commands::Providers.new.execute
26
+ #
8
27
  class Providers < Base
9
28
  include RubyTerraform::Options::Common
10
29
 
30
+ # @!visibility private
11
31
  def subcommands
12
32
  %w[providers]
13
33
  end
34
+
35
+ # @todo Add directory argument
14
36
  end
15
37
  end
16
38
  end
@@ -5,13 +5,77 @@ require_relative '../options/common'
5
5
 
6
6
  module RubyTerraform
7
7
  module Commands
8
+ # Wraps the +terraform providers lock+ command which writes out dependency
9
+ # locks for the configured providers.
10
+ #
11
+ # Normally the dependency lock file (.terraform.lock.hcl) is updated
12
+ # automatically by "terraform init", but the information available to the
13
+ # normal provider installer can be constrained when you're installing
14
+ # providers from filesystem or network mirrors, and so the generated lock
15
+ # file can end up incomplete.
16
+ #
17
+ # The "providers lock" subcommand addresses that by updating the lock file
18
+ # based on the official packages available in the origin registry, ignoring
19
+ # the currently-configured installation strategy.
20
+ #
21
+ # After this command succeeds, the lock file will contain suitable checksums
22
+ # to allow installation of the providers needed by the current configuration
23
+ # on all of the selected platforms.
24
+ #
25
+ # By default this command updates the lock file for every provider declared
26
+ # in the configuration. You can override that behavior by providing one or
27
+ # more provider source addresses on the command line.
28
+ #
29
+ # For options accepted on construction, see {#initialize}.
30
+ #
31
+ # When executing an instance of {ProvidersLock} via {#execute}, the
32
+ # following options are supported:
33
+ #
34
+ # * +:providers+: the provider source addresses for which the lock file
35
+ # should be updated.
36
+ # * +:chdir+: the path of a working directory to switch to before executing
37
+ # the given subcommand.
38
+ # * +:fs_mirror+: if provided, consults the given filesystem mirror
39
+ # directory instead of the origin registry for each of the given
40
+ # providers; this would be necessary to generate lock file entries for
41
+ # a provider that is available only via a mirror, and not published in an
42
+ # upstream registry; in this case, the set of valid checksums will be
43
+ # limited only to what Terraform can learn from the data in the mirror
44
+ # directory.
45
+ # * +:net_mirror+: if provided, consults the given network mirror (given as
46
+ # a base URL) instead of the origin registry for each of the given
47
+ # providers; this would be necessary to generate lock file entries for a
48
+ # provider that is available only via a mirror, and not published in an
49
+ # upstream registry; in this case, the set of valid checksums will be
50
+ # limited only to what Terraform can learn from the data in the mirror
51
+ # indices.
52
+ # * +:platform+: the target platform to request package checksums for; by
53
+ # default Terraform will request package checksums suitable only for the
54
+ # platform where you run this command; target names consist of an
55
+ # operating system and a CPU architecture; for example, "linux_amd64"
56
+ # selects the Linux operating system running on an AMD64 or x86_64 CPU;
57
+ # each provider is available only for a limited set of target platforms;
58
+ # if both +:platform+ and +:platforms+ are provided, all platforms will be
59
+ # passed to Terraform.
60
+ # * +:platforms+: an array of target platforms to request package checksums
61
+ # for; see +:platform+ for more details; if both +:platform+ and
62
+ # +:platforms+ are provided, all platforms will be passed to Terraform.
63
+ #
64
+ # @example Basic Invocation
65
+ # RubyTerraform::Commands::ProvidersLock.new.execute(
66
+ # fs_mirror: "/usr/local/terraform/providers",
67
+ # platforms: ["windows_amd64", "darwin_amd64", "linux_amd64"],
68
+ # providers: "tf.example.com/ourcompany/ourplatform")
69
+ #
8
70
  class ProvidersLock < Base
9
71
  include RubyTerraform::Options::Common
10
72
 
73
+ # @!visibility private
11
74
  def subcommands
12
75
  %w[providers lock]
13
76
  end
14
77
 
78
+ # @!visibility private
15
79
  def options
16
80
  %w[
17
81
  -fs-mirror
@@ -20,6 +84,8 @@ module RubyTerraform
20
84
  ] + super
21
85
  end
22
86
 
87
+ # @!visibility private
88
+ # @todo Flatten arguments array to allow array of providers.
23
89
  def arguments(parameters)
24
90
  [parameters[:providers]]
25
91
  end
@@ -5,17 +5,59 @@ require_relative '../options/common'
5
5
 
6
6
  module RubyTerraform
7
7
  module Commands
8
+ # Wraps the +terraform providers mirror+ command which saves local copies of
9
+ # all required provider plugins.
10
+ #
11
+ # Populates a local directory with copies of the provider plugins needed for
12
+ # the current configuration, so that the directory can be used either
13
+ # directly as a filesystem mirror or as the basis for a network mirror and
14
+ # thus obtain those providers without access to their origin registries in
15
+ # future.
16
+ #
17
+ # The mirror directory will contain JSON index files that can be published
18
+ # along with the mirrored packages on a static HTTP file server to produce a
19
+ # network mirror. Those index files will be ignored if the directory is used
20
+ # instead as a local filesystem mirror.
21
+ #
22
+ # For options accepted on construction, see {#initialize}.
23
+ #
24
+ # When executing an instance of {ProvidersMirror} via {#execute}, the
25
+ # following options are supported:
26
+ #
27
+ # * +:directory+: the directory to populate with the mirrored provider
28
+ # plugins.
29
+ # * +:chdir+: the path of a working directory to switch to before executing
30
+ # the given subcommand.
31
+ # * +:platform+: the target platform to build a mirror for; by default
32
+ # Terraform will obtain plugin packages suitable for the platform where
33
+ # you run this command; target names consist of an operating system and a
34
+ # CPU architecture; for example, "linux_amd64" selects the Linux operating
35
+ # system running on an AMD64 or x86_64 CPU; each provider is available
36
+ # only for a limited set of target platforms; if both +:platform+ and
37
+ # +:platforms+ are provided, all platforms will be passed to Terraform.
38
+ # * +:platforms+: an array of target platforms to build a mirror for for;
39
+ # see +:platform+ for more details; if both +:platform+ and +:platforms+
40
+ # are provided, all platforms will be passed to Terraform.
41
+ #
42
+ # @example Basic Invocation
43
+ # RubyTerraform::Commands::PlatformsMirror.new.execute(
44
+ # directory: './plugins',
45
+ # platforms: ["windows_amd64", "darwin_amd64", "linux_amd64"])
46
+ #
8
47
  class ProvidersMirror < Base
9
48
  include RubyTerraform::Options::Common
10
49
 
50
+ # @!visibility private
11
51
  def subcommands
12
52
  %w[providers mirror]
13
53
  end
14
54
 
55
+ # @!visibility private
15
56
  def options
16
57
  %w[-platform] + super
17
58
  end
18
59
 
60
+ # @!visibility private
19
61
  def arguments(parameters)
20
62
  [parameters[:directory]]
21
63
  end
@@ -18,7 +18,8 @@ module RubyTerraform
18
18
  -backup
19
19
  -lock
20
20
  -lock-timeout
21
- -state -state-out
21
+ -state
22
+ -state-out
22
23
  -ignore-remote-version
23
24
  ] + super
24
25
  end
@@ -1,8 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'options/name'
4
- require_relative 'options/types/flag'
5
- require_relative 'options/types/boolean'
6
- require_relative 'options/types/standard'
4
+ require_relative 'options/types'
5
+ require_relative 'options/values'
6
+ require_relative 'options/definition'
7
7
  require_relative 'options/factory'
8
8
  require_relative 'options/common'
9
+
10
+ module RubyTerraform
11
+ module Options
12
+ def self.name(name)
13
+ Name.new(name)
14
+ end
15
+
16
+ def self.definition(opts)
17
+ Definition.new(opts)
18
+ end
19
+
20
+ def self.types
21
+ Types
22
+ end
23
+
24
+ def self.values
25
+ Values
26
+ end
27
+ end
28
+ end
29
+
30
+ require_relative 'options/definitions'
@@ -3,6 +3,7 @@
3
3
  module RubyTerraform
4
4
  module Options
5
5
  module Common
6
+ # @!visibility private
6
7
  def options
7
8
  %w[-chdir]
8
9
  end
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'immutable-struct'
4
+
5
+ require_relative 'name'
6
+ require_relative 'types'
7
+ require_relative 'values'
8
+
9
+ module RubyTerraform
10
+ module Options
11
+ # rubocop:disable Metrics/ClassLength
12
+ class Definition < ImmutableStruct.new(
13
+ :name,
14
+ :option_type,
15
+ :value_type,
16
+ :override_keys,
17
+ :extra_keys,
18
+ :separator,
19
+ :repeatable?
20
+ )
21
+ # rubocop:disable Metrics/MethodLength
22
+ def initialize(opts)
23
+ raise 'Missing name.' unless opts[:name]
24
+
25
+ super(
26
+ name: Name.new(opts[:name]),
27
+ option_type: Types.resolve(opts[:option_type]) || Types::Standard,
28
+ value_type: Values.resolve(opts[:value_type]) || Values::String,
29
+ repeatable: opts[:repeatable] || false,
30
+ separator: opts[:separator],
31
+ extra_keys:
32
+ { singular: [], plural: [] }
33
+ .merge(opts[:extra_keys] || {}),
34
+ override_keys:
35
+ { singular: nil, plural: nil }
36
+ .merge(opts[:override_keys] || {})
37
+ )
38
+ end
39
+ # rubocop:enable Metrics/MethodLength
40
+
41
+ def matches?(name)
42
+ @name == Name.new(name)
43
+ end
44
+
45
+ def build(parameters)
46
+ build_singular_options(parameters) + build_plural_options(parameters)
47
+ end
48
+
49
+ private
50
+
51
+ def resolved_singular_key
52
+ if override_keys[:singular] == false
53
+ nil
54
+ else
55
+ override_keys[:singular] || name.as_singular_key
56
+ end
57
+ end
58
+
59
+ def all_singular_keys
60
+ ([resolved_singular_key] + extra_keys[:singular]).compact
61
+ end
62
+
63
+ def resolved_plural_key
64
+ if override_keys[:plural] == false
65
+ nil
66
+ else
67
+ override_keys[:plural] || name.as_plural_key
68
+ end
69
+ end
70
+
71
+ def all_plural_keys
72
+ ([resolved_plural_key] + extra_keys[:plural]).compact
73
+ end
74
+
75
+ def too_many_values?(values)
76
+ !repeatable? && values.length > 1
77
+ end
78
+
79
+ def values(parameters, keys)
80
+ keys.map { |k| parameters[k] }.compact
81
+ end
82
+
83
+ def needs_plural?(value)
84
+ repeatable? && !value.nil?
85
+ end
86
+
87
+ def only_singular?(value)
88
+ !needs_plural?(value)
89
+ end
90
+
91
+ def key_valued?(value)
92
+ value.respond_to?(:keys)
93
+ end
94
+
95
+ def multi_valued?(value)
96
+ value.respond_to?(:each)
97
+ end
98
+
99
+ def build_option(value)
100
+ option_type.new(name, value, separator: separator)
101
+ end
102
+
103
+ def build_value(value)
104
+ value_type.new(value)
105
+ end
106
+
107
+ def build_key_value(key, value)
108
+ Values::KeyValue.new(key, build_value(value))
109
+ end
110
+
111
+ def build_singular(value)
112
+ build_single_option(value)
113
+ end
114
+
115
+ def build_singulars(values)
116
+ values.map { |p| build_singular(p) }.flatten
117
+ end
118
+
119
+ def build_singular_options(parameters)
120
+ keys = all_singular_keys
121
+ values = values(parameters, keys)
122
+
123
+ if too_many_values?(values)
124
+ raise "Multiple values provided for '#{name}' " \
125
+ "(with keys #{keys}) and option not repeatable."
126
+ end
127
+
128
+ build_singulars(values)
129
+ end
130
+
131
+ def build_plural(value)
132
+ if only_singular?(value)
133
+ build_no_options
134
+ elsif key_valued?(value)
135
+ build_key_value_options(value)
136
+ elsif multi_valued?(value)
137
+ build_multiple_options(value)
138
+ else
139
+ build_single_option(value)
140
+ end
141
+ end
142
+
143
+ def build_plurals(values)
144
+ values.map { |p| build_plural(p) }.flatten
145
+ end
146
+
147
+ def build_plural_options(parameters)
148
+ keys = all_plural_keys
149
+ values = values(parameters, keys)
150
+
151
+ build_plurals(values)
152
+ end
153
+
154
+ def build_key_value_options(value)
155
+ value.map { |k, v| build_option(build_key_value(k, v)) }
156
+ end
157
+
158
+ def build_multiple_options(value)
159
+ value.map { |v| build_option(build_value(v)) }
160
+ end
161
+
162
+ def build_single_option(value)
163
+ [build_option(build_value(value))]
164
+ end
165
+
166
+ def build_no_options
167
+ []
168
+ end
169
+ end
170
+ # rubocop:enable Metrics/ClassLength
171
+ end
172
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyTerraform
4
+ module Options
5
+ DEFINITIONS =
6
+ [
7
+ # complex repeatable options with space separator
8
+ %w[-var].map do |o|
9
+ definition(
10
+ name: o, option_type: :standard, value_type: :complex,
11
+ repeatable: true, separator: ' '
12
+ )
13
+ end,
14
+
15
+ # complex repeatable options with default separator
16
+ %w[-backend-config].map do |o|
17
+ definition(
18
+ name: o, option_type: :standard, value_type: :complex,
19
+ repeatable: true,
20
+ override_keys: { singular: false, plural: :backend_config }
21
+ )
22
+ end,
23
+
24
+ # string repeatable options
25
+ %w[-var-file -target -platform].map do |o|
26
+ definition(
27
+ name: o, option_type: :standard, value_type: :string,
28
+ repeatable: true
29
+ )
30
+ end,
31
+
32
+ # boolean options
33
+ %w[
34
+ -auto-approve
35
+ -backend
36
+ -get
37
+ -get-plugins
38
+ -input
39
+ -list
40
+ -lock
41
+ -refresh
42
+ -upgrade
43
+ -verify-plugins
44
+ -write
45
+ ].map do |o|
46
+ definition(name: o, option_type: :standard, value_type: :boolean)
47
+ end,
48
+
49
+ # flag options
50
+ %w[
51
+ -allow-missing
52
+ -allow-missing-config
53
+ -check
54
+ -compact-warnings
55
+ -destroy
56
+ -detailed-exitcode
57
+ -diff
58
+ -draw-cycles
59
+ -force
60
+ -force-copy
61
+ -ignore-remote-version
62
+ -json
63
+ -no-color
64
+ -raw
65
+ -reconfigure
66
+ -recursive
67
+ -update
68
+ ].map do |o|
69
+ definition(name: o, option_type: :flag, value_type: :boolean)
70
+ end,
71
+
72
+ # string options
73
+ %w[
74
+ -backup
75
+ -backup-out
76
+ -chdir
77
+ -from-module
78
+ -fs-mirror
79
+ -lock-timeout
80
+ -module-depth
81
+ -net-mirror
82
+ -parallelism
83
+ -plugin-dir
84
+ -provider
85
+ -state
86
+ -state-out
87
+ -type
88
+ ].map do |o|
89
+ definition(name: o, option_type: :standard, value_type: :string)
90
+ end,
91
+
92
+ # string options with extra keys
93
+ definition(
94
+ name: '-config', option_type: :standard, value_type: :string,
95
+ extra_keys: { singular: %i[directory] }
96
+ ),
97
+ definition(
98
+ name: '-out', option_type: :standard, value_type: :string,
99
+ extra_keys: { singular: %i[plan] }
100
+ )
101
+ ].flatten.freeze
102
+ end
103
+ end