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

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