cem_acpt 0.10.8 → 0.10.9

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: 93cbd3354b97e498b8eba13d18b40a0294147c2e5d499ee3ce3a8c3cd809637d
4
- data.tar.gz: d5879ac35af8d5fa25f4207b9efea2bc51fda8718a65a49aa38a87e7cb74e766
3
+ metadata.gz: 34279d516f9561d412312959bbe0180d406a234818e4311c2238983922900de5
4
+ data.tar.gz: cd20359cc64580a648f74964ceb6847c7c60db987cc96dca76ab30cfd0f1a877
5
5
  SHA512:
6
- metadata.gz: c02e967c85cc1b00840e2263f292af3a911d4675be2509228ad822d5014d586c7282cc81c6ea071d078970b7a7dcbdcf29755ea3c4befe56a1cb7209740d6fef
7
- data.tar.gz: a0d1beae7b3ebe208a5310beccf5c8ba176f82a3840affad465cc7cf9ac47d76a1ae8b0eb8fc9f7d806302333bba3cd03b43b14ab9818212cefe57bc61330e92
6
+ metadata.gz: cb06435dc76fe50ff0dffd557db70d0e354a80093cffed96335580601e00d56dbc43a41805fb621c67177d0cf7c97d67ff33f19e90f3e871516dbcddf0661606
7
+ data.tar.gz: ffb32d8da0e509d56c828b2bcd356e2e0454ec138713991636881f75ed43da8dfe44f16d8d26e5c700ed0940a645d8e084842f916e5abce4b5218919f4787f91
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cem_acpt (0.10.8)
4
+ cem_acpt (0.10.9)
5
5
  async-http (>= 0.60, < 0.70)
6
6
  bcrypt_pbkdf (>= 1.0, < 2.0)
7
7
  deep_merge (>= 1.2, < 2.0)
@@ -48,6 +48,10 @@ module CemAcpt
48
48
  end
49
49
 
50
50
  # A wrapper around provision_commands that allows for extra commands to be added for a specific OS version(i.e EL 8)
51
+ # @param image_name [String] The name of the OS image being provisioned.
52
+ # @return [Array<String>] An array of shell commands to be run on the provisioned nodes to set up the necessary
53
+ # environment for running the Puppet manifest, including any additional commands needed for specific OS
54
+ # versions.
51
55
  def provision_commands_wrapper(image_name)
52
56
  if ['rhel-8', 'oel-8', 'alma-8', 'rocky-8'].any? { |el8| image_name.include?(el8) }
53
57
  commands = [
@@ -68,6 +72,9 @@ module CemAcpt
68
72
 
69
73
  private
70
74
 
75
+ # @return [String] The command to apply the Puppet manifest on the provisioned nodes, including any necessary
76
+ # options for logging and debugging. This command is constructed based on the configuration settings for the
77
+ # provisioner, and may include additional options for debug and verbose logging if those settings are enabled.
71
78
  def apply_command
72
79
  cmd = [
73
80
  'sudo',
@@ -9,6 +9,11 @@ module CemAcpt
9
9
  include CemAcpt::Logging
10
10
  extend CemAcpt::Logging
11
11
 
12
+ # Determines if this OsData implementation should be used for the given test name. This method extracts the OS
13
+ # name and version from the test name using a regular expression, and checks if they match the valid names and
14
+ # versions defined by the subclass. The test name is expected to be in the format `<prefix>_osname-version`, where
15
+ # `osname` is the name of the operating system and `version` is the version number. For example, a test name of
16
+ # `test_ubuntu-20` would indicate an Ubuntu OS with version 20.
12
17
  def self.use_for?(test_name)
13
18
  name_ver = test_name.match(%r{^\w+_(\w+)-(\d+).*})
14
19
  return false unless name_ver && name_ver.length == 3
@@ -20,50 +25,78 @@ module CemAcpt
20
25
  false
21
26
  end
22
27
 
28
+ # Returns an array of valid OS names that this class can handle. This method should be implemented by subclasses
29
+ # to specify which OS names they can handle. The OS name is typically extracted from the test name and used to
30
+ # determine which OS-specific data class to use for provisioning.
31
+ # @return [Array<String>] An array of valid OS names that this class can handle.
23
32
  def self.valid_names
24
33
  raise NotImplementedError
25
34
  end
26
35
 
36
+ # Returns an array of valid OS versions that this class can handle. This method should be implemented by
37
+ # subclasses to specify which OS versions they can handle. The OS version is typically extracted from the test
38
+ # name and used to determine which OS-specific data class to use for provisioning.
39
+ # @return [Array<String>] An array of valid OS versions that this class can handle.
27
40
  def self.valid_versions
28
41
  raise NotImplementedError
29
42
  end
30
43
 
31
44
  attr_accessor :base_provision_directory
32
45
 
46
+ # Initializes a new instance of the OsData class with the given configuration and provision data.
47
+ # @param config [CemAcpt::Config] The configuration object containing settings for the provisioner.
48
+ # @param provision_data [Hash] A hash containing all necessary information for provisioning, including node data,
49
+ # credentials, and module package paths.
33
50
  def initialize(config, provision_data)
34
51
  @config = config
35
52
  @provision_data = provision_data
36
53
  @base_provision_directory = @config.get('terraform.dir')
37
54
  end
38
55
 
56
+ # Returns the path to the Puppet binary on the provisioned nodes. This method should be implemented by subclasses
57
+ # to specify the correct path to the Puppet binary for the specific OS they handle.
58
+ # @return [String] The path to the Puppet binary on the provisioned nodes.
39
59
  def puppet_bin_path
40
60
  raise NotImplementedError
41
61
  end
42
62
 
63
+ # @return [String] The filename of the Puppet manifest to be used for provisioning.
43
64
  def puppet_manifest_file
44
65
  'manifest.pp'
45
66
  end
46
67
 
68
+ # @return [String] The name of the remote package file that will be created on the provisioned nodes for
69
+ # installing the Puppet module.
47
70
  def remote_module_package_name
48
71
  'puppet-module.tar.gz'
49
72
  end
50
73
 
74
+ # @return [String] The name of the OsData implementation, derived from the class name.
51
75
  def implementation_name
52
76
  self.class.to_s.downcase.split('::').last
53
77
  end
54
78
 
79
+ # @return [String] The path to the provision directory for this OsData implementation, which is a subdirectory of
80
+ # the base provision directory named after the implementation.
55
81
  def provision_directory
56
82
  File.join(base_provision_directory, implementation_name)
57
83
  end
58
84
 
85
+ # @return [String] The path to the destination provision directory on the provisioned nodes. This method should be
86
+ # implemented by subclasses to specify the correct path for the specific OS they handle.
59
87
  def destination_provision_directory
60
88
  raise NotImplementedError
61
89
  end
62
90
 
91
+ # @return [Array<String>] An array of shell commands to be run on the provisioned nodes to set up the necessary
92
+ # environment for running the Puppet manifest. This method should be implemented by subclasses to specify the
93
+ # correct commands for the specific OS they handle.
63
94
  def provision_commands
64
95
  raise NotImplementedError
65
96
  end
66
97
 
98
+ # @return [Array<String>] An array of filenames for Goss test files that should be included in the provision
99
+ # directory.
67
100
  def goss_files
68
101
  Dir.glob(File.join(provision_directory, 'goss', '*.yaml')).map { |f| File.basename(f) }
69
102
  end
@@ -15,26 +15,43 @@ module CemAcpt
15
15
  attr_accessor :working_dir
16
16
  attr_reader :bin_path
17
17
 
18
+ # Initializes a new TerraformCmd instance.
19
+ # @param working_dir [String, nil] The working directory to run terraform commands in.
20
+ # @param environment [Hash] A hash of environment variables to set when running terraform commands. These will be
21
+ # merged with any additional environment variables passed in when running commands.
18
22
  def initialize(working_dir = nil, environment = {})
19
23
  @working_dir = working_dir
20
24
  @environment = environment
21
25
  @bin_path = which_terraform
22
26
  end
23
27
 
28
+ # @return [String] A string representation of the TerraformCmd instance.
24
29
  def inspect
25
30
  to_s
26
31
  end
27
32
 
33
+ # @return [String] A string representation of the TerraformCmd instance, which includes the class name and object
34
+ # ID.
28
35
  def to_s
29
36
  "#<#{self.class.name}:0x#{object_id.to_s(16)}>"
30
37
  end
31
38
 
39
+ # Sets the environment variables to be used when running terraform commands. This will replace any existing
40
+ # environment variables set on the instance.
41
+ # @param env [Hash] A hash of environment variables to set when running terraform commands. These will be merged with any additional environment variables passed in when running commands.
42
+ # @raise [ArgumentError] If the provided environment is not a Hash.
32
43
  def environment=(env)
33
44
  raise ArgumentError, 'environment must be a Hash' unless env.is_a?(Hash)
34
45
 
35
46
  @environment = env
36
47
  end
37
48
 
49
+ # Returns a hash of environment variables to be used when running terraform commands. This will merge any
50
+ # environment variables set on the instance with any additional environment variables passed in. Passed in
51
+ # environment variables will take precedence over those set on the instance, but will not persist on the instance.
52
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance.
53
+ # @return [Hash] A hash of environment variables to be used when running terraform commands.
54
+ # @raise [ArgumentError] If the provided additional environment is not a Hash.
38
55
  def environment(env = {})
39
56
  raise ArgumentError, 'additional environment must be a Hash' unless env.is_a?(Hash)
40
57
 
@@ -44,32 +61,92 @@ module CemAcpt
44
61
  @environment.merge(env)
45
62
  end
46
63
 
47
- def init(opts = {}, env = {})
48
- run_cmd('init', opts, env)
49
- end
50
-
51
- def plan(opts = {}, env = {})
64
+ # Runs the `terraform init` command with the provided options and environment variables.
65
+ # @param opts [Hash] A hash of options to pass to the `terraform init` command.
66
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance when
67
+ # running the command.
68
+ # @param raise_on_fail [Boolean] Whether to raise an error if the command fails. Defaults to true.
69
+ # @param combine_out_err [Boolean] Whether to combine the output and error streams into the output. If false, the
70
+ # stderr stream will not be written to the output stream or returned with the output string. Defaults to true.
71
+ # @return [String] The string output of the command.
72
+ def init(opts = {}, env = {}, raise_on_fail: true, combine_out_err: true)
73
+ run_cmd('init', opts, env, raise_on_fail: raise_on_fail, combine_out_err: combine_out_err)
74
+ end
75
+
76
+ # Runs the `terraform plan` command with the provided options and environment variables. The :plan option is
77
+ # required and will be used as the output file for the plan.
78
+ # @param opts [Hash] A hash of options to pass to the `terraform plan` command. The :plan option is required and
79
+ # will be used as the output file for the plan.
80
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance when
81
+ # running the command.
82
+ # @param raise_on_fail [Boolean] Whether to raise an error if the command fails. Defaults to true.
83
+ # @param combine_out_err [Boolean] Whether to combine the output and error streams into the output. If false, the
84
+ # stderr stream will not be written to the output stream or returned with the output string. Defaults to true.
85
+ # @return [String] The string output of the command.
86
+ # @raise [ArgumentError] If the :plan option is not provided in the opts hash or is nil/empty.
87
+ def plan(opts = {}, env = {}, raise_on_fail: true, combine_out_err: true)
52
88
  plan = extract_arg!(opts, :plan, required: true)
53
89
  opts[:out] = plan
54
- run_cmd('plan', opts, env)
55
- end
56
-
57
- def apply(opts = {}, env = {})
90
+ run_cmd('plan', opts, env, raise_on_fail: raise_on_fail, combine_out_err: combine_out_err)
91
+ end
92
+
93
+ # Runs the `terraform apply` command with the provided options and environment variables. The :plan option is
94
+ # required and will be used as the input file for the apply.
95
+ # @param opts [Hash] A hash of options to pass to the `terraform apply` command. The :plan option is required and
96
+ # will be used as the input file for the apply.
97
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance when
98
+ # running the command.
99
+ # @param raise_on_fail [Boolean] Whether to raise an error if the command fails. Defaults to true.
100
+ # @param combine_out_err [Boolean] Whether to combine the output and error streams into the output. If false, the
101
+ # stderr stream will not be written to the output stream or returned with the output string. Defaults to true.
102
+ # @return [String] The string output of the command.
103
+ # @raise [ArgumentError] If the :plan option is not provided in the opts hash or is nil/empty.
104
+ def apply(opts = {}, env = {}, raise_on_fail: true, combine_out_err: true)
58
105
  plan = extract_arg!(opts, :plan, required: true)
59
- run_cmd('apply', opts, env, suffix: plan)
60
- end
61
-
62
- def destroy(opts = {}, env = {})
63
- run_cmd('destroy', opts, env)
64
- end
65
-
66
- def show(opts = {}, env = {})
67
- run_cmd('show', opts, env)
68
- end
69
-
70
- def output(opts = {}, env = {})
106
+ run_cmd('apply', opts, env, suffix: plan, raise_on_fail: raise_on_fail, combine_out_err: combine_out_err)
107
+ end
108
+
109
+ # Runs the `terraform destroy` command with the provided options and environment variables.
110
+ # @param opts [Hash] A hash of options to pass to the `terraform destroy` command.
111
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance when
112
+ # running the command.
113
+ # @param raise_on_fail [Boolean] Whether to raise an error if the command fails. Defaults to true.
114
+ # @param combine_out_err [Boolean] Whether to combine the output and error streams into the output. If false, the
115
+ # stderr stream will not be written to the output stream or returned with the output string. Defaults to true.
116
+ # @return [String] The string output of the command.
117
+ def destroy(opts = {}, env = {}, raise_on_fail: true, combine_out_err: true)
118
+ run_cmd('destroy', opts, env, raise_on_fail: raise_on_fail, combine_out_err: combine_out_err)
119
+ end
120
+
121
+ # Runs the `terraform show` command with the provided options and environment variables.
122
+ # @param opts [Hash] A hash of options to pass to the `terraform show` command.
123
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance when
124
+ # running the command.
125
+ # @param raise_on_fail [Boolean] Whether to raise an error if the command fails. Defaults to true.
126
+ # @param combine_out_err [Boolean] Whether to combine the output and error streams into the output. If false, the
127
+ # stderr stream will not be written to the output stream or returned with the output string. Defaults to true.
128
+ # @return [String] The string output of the command.
129
+ def show(opts = {}, env = {}, raise_on_fail: true, combine_out_err: true)
130
+ run_cmd('show', opts, env, raise_on_fail: raise_on_fail, combine_out_err: combine_out_err)
131
+ end
132
+
133
+ # Runs the `terraform output` command with the provided options and environment variables. The :name option is
134
+ # required and will be used as the name of the output to show.
135
+ # @param opts [Hash] A hash of options to pass to the `terraform output` command. The :name option is required and
136
+ # will be used as the name of the output to show.
137
+ # @param env [Hash] A hash of additional environment variables to merge with those set on the instance when
138
+ # running the command.
139
+ # @param raise_on_fail [Boolean] Whether to raise an error if the command fails. Defaults to true.
140
+ # @param combine_out_err [Boolean] Whether to combine the output and error streams into the output. If false, the
141
+ # stderr stream will not be written to the output stream or returned with the output string. Defaults to false
142
+ # because output command is typically used to get specific output values and we don't want error messages
143
+ # mixed in with the output. Setting this to true can cause JSON parsing of the output to fail if there are error
144
+ # messages included in the output string.
145
+ # @return [String] The string output of the command.
146
+ # @raise [ArgumentError] If the :name option is not provided in the opts hash or is nil/empty.
147
+ def output(opts = {}, env = {}, raise_on_fail: true, combine_out_err: false)
71
148
  name = extract_arg!(opts, :name, required: true)
72
- run_cmd('output', opts, env, suffix: name)
149
+ run_cmd('output', opts, env, suffix: name, raise_on_fail: raise_on_fail, combine_out_err: combine_out_err)
73
150
  end
74
151
 
75
152
  private
@@ -81,11 +158,12 @@ module CemAcpt
81
158
  opts.delete(key)
82
159
  end
83
160
 
84
- def run_cmd(cmd, opts = {}, env = {}, suffix: '')
161
+ def run_cmd(cmd, opts = {}, env = {}, suffix: '', raise_on_fail: true, combine_out_err: true)
85
162
  cmd = format_cmd(cmd, opts, suffix)
86
163
  env = environment(env)
87
164
  logger.debug('CemAcpt::Provision::TerraformCmd') { "Running command \"#{cmd}\" with environment \"#{env}\"" }
88
- CemAcpt::Utils::Shell.run_cmd(cmd, env, output: logger)
165
+ CemAcpt::Utils::Shell.run_cmd(cmd, env, output: logger, raise_on_fail: raise_on_fail,
166
+ combine_out_err: combine_out_err)
89
167
  end
90
168
 
91
169
  def chdir(opts = {})
@@ -9,6 +9,9 @@ require_relative 'terraform/terraform_cmd'
9
9
 
10
10
  module CemAcpt
11
11
  module Provision
12
+ # Class to handle provisioning infrastructure using Terraform. This class abstracts away the details of running
13
+ # Terraform commands and managing the working directory, allowing for easy provisioning and destruction of
14
+ # infrastructure for testing purposes.
12
15
  class Terraform
13
16
  DEFAULT_PLAN_NAME = 'testplan.tfplan'
14
17
  DEFAULT_VARS_FILE = 'testvars.json'
@@ -16,6 +19,14 @@ module CemAcpt
16
19
 
17
20
  attr_reader :environment, :working_dir, :module_package_path, :private_key, :public_key
18
21
 
22
+ # Initializes a new Terraform provisioner with the given configuration and provision data. The provision data
23
+ # should include all necessary information about the nodes to be provisioned, as well as any necessary
24
+ # credentials and module package paths. The configuration should include any necessary settings for the
25
+ # provisioner, such as the base directory for Terraform working directories and any environment variables to
26
+ # set when running Terraform commands.
27
+ # @param config [CemAcpt::Config] The configuration object containing settings for the provisioner.
28
+ # @param provision_data [Hash] A hash containing all necessary information for provisioning, including node data,
29
+ # credentials, and module package paths.
19
30
  def initialize(config, provision_data)
20
31
  @config = config
21
32
  @provision_data = provision_data
@@ -28,7 +39,10 @@ module CemAcpt
28
39
  @applied = false
29
40
  end
30
41
 
31
- # @return [Hash] A hash of instance names and IPs
42
+ # Provisions infrastructure using Terraform and returns a hash of instance names and IPs.
43
+ # @param reuse_working_dir [Boolean] Whether to reuse the existing working directory if it exists. Defaults to
44
+ # false.
45
+ # @return [Hash] A hash of instance names and IPs.
32
46
  def provision(reuse_working_dir: false)
33
47
  logger.info('CemAcpt::Provision::Terraform') { 'Provisioning nodes...' }
34
48
  @working_dir = new_working_dir unless reuse_working_dir
@@ -40,6 +54,10 @@ module CemAcpt
40
54
  @applied = true
41
55
  end
42
56
 
57
+ # Returns the output of the Terraform apply command as a hash of instance names and IPs.
58
+ # @return [Hash] A hash of instance names and IPs.
59
+ # @raise [RuntimeError] If Terraform has not been applied yet.
60
+ # @raise [JSON::ParserError] If there is an error parsing the Terraform output.
43
61
  def output
44
62
  raise 'Terraform has not been applied yet' unless @applied
45
63
 
@@ -51,6 +69,7 @@ module CemAcpt
51
69
  raise e
52
70
  end
53
71
 
72
+ # Destroys the infrastructure provisioned by Terraform and deletes the working directory.
54
73
  def destroy
55
74
  terraform_destroy(formatted_vars)
56
75
  logger.verbose('CemAcpt::Provision::Terraform') { "Deleting old working directory #{working_dir}" }
@@ -61,21 +80,32 @@ module CemAcpt
61
80
  @public_key = nil
62
81
  end
63
82
 
83
+ # Shows the current state of the Terraform-managed infrastructure.
64
84
  def show
65
85
  terraform_show
66
86
  end
67
87
 
68
88
  private
69
89
 
90
+ # @return [CemAcpt::Provision::TerraformCmd] An instance of the TerraformCmd class, which provides methods for
91
+ # running Terraform commands.
70
92
  def terraform
71
93
  @terraform ||= CemAcpt::Provision::TerraformCmd.new(working_dir, environment)
72
94
  end
73
95
 
96
+ # Initializes the Terraform working directory by running `terraform init`. This method should be called before
97
+ # running any other Terraform commands to ensure that the working directory is properly set up.
74
98
  def terraform_init
75
99
  logger.info('CemAcpt::Provision::Terraform') { 'Initializing Terraform' }
76
100
  terraform.init({ chdir: working_dir, input: false, no_color: true }, { environment: environment })
77
101
  end
78
102
 
103
+ # Runs `terraform plan` with the given variables and plan name. This method generates a Terraform plan file that
104
+ # can then be applied using the `terraform_apply` method. The variables should be passed as a hash, and will be
105
+ # converted to JSON and saved to a file in the working directory for use by Terraform.
106
+ # @param vars [Hash] A hash of variables to pass to Terraform. These will be converted to JSON and saved to a file
107
+ # in the working directory for use by Terraform.
108
+ # @param plan_name [String] The name of the Terraform plan file to create. Defaults to `testplan.tfplan`.
79
109
  def terraform_plan(vars, plan_name = DEFAULT_PLAN_NAME)
80
110
  logger.info('CemAcpt::Provision::Terraform') { "Creating Terraform plan '#{plan_name}'" }
81
111
  logger.verbose('CemAcpt::Provision::Terraform') { "Using vars:\n#{JSON.pretty_generate(vars)}" }
@@ -93,16 +123,32 @@ module CemAcpt
93
123
  )
94
124
  end
95
125
 
126
+ # Runs `terraform apply` with the given plan name. This method applies the Terraform plan generated by the
127
+ # `terraform_plan` method to provision the infrastructure. The plan name should match the name of the plan file
128
+ # generated by the `terraform_plan` method.
129
+ # @param plan_name [String] The name of the Terraform plan file to apply. Defaults to `testplan.tfplan`.
96
130
  def terraform_apply(plan_name = DEFAULT_PLAN_NAME)
97
131
  logger.info('CemAcpt::Provision::Terraform') { "Running Terraform apply with the plan #{plan_name}" }
98
132
  terraform.apply({ chdir: working_dir, input: false, no_color: true, plan: plan_name }, { environment: environment })
99
133
  end
100
134
 
135
+ # Runs `terraform output` to get the output of the Terraform apply command. This method can be used to retrieve
136
+ # any outputs defined in the Terraform configuration, such as instance names and IPs. The output will be returned
137
+ # as a string, which can then be parsed as JSON if the `json` parameter is set to true.
138
+ # @param name [String] The name of the Terraform output to retrieve. This should match the name of an output
139
+ # defined in the Terraform configuration.
140
+ # @param json [Boolean] Whether to parse the output as JSON. If true, the output will be returned as a string and
141
+ # should be parsed as JSON by the caller. If false, the raw string output from Terraform will be returned.
142
+ # Defaults to true.
101
143
  def terraform_output(name, json: true)
102
144
  logger.info('CemAcpt::Provision::Terraform') { "Getting Terraform output #{name}" }
103
145
  terraform.output({ chdir: working_dir, no_color: true, json: json, name: name }, { environment: environment })
104
146
  end
105
147
 
148
+ # Runs `terraform destroy` to destroy the infrastructure provisioned by Terraform. This method should be called
149
+ # when you want to remove all resources created by Terraform.
150
+ # @param vars [Hash] A hash of variables to pass to Terraform. These should be the same variables that were used
151
+ # to provision the infrastructure.
106
152
  def terraform_destroy(vars)
107
153
  logger.info('CemAcpt::Provision::Terraform') { 'Destroying Terraform resources...' }
108
154
  logger.verbose('CemAcpt::Provision::Terraform') { "Using vars: #{vars}" }
@@ -120,11 +166,20 @@ module CemAcpt
120
166
  )
121
167
  end
122
168
 
169
+ # Runs `terraform show` to display the current state of the Terraform-managed infrastructure.
123
170
  def terraform_show
124
171
  logger.info('CemAcpt::Provision::Terraform') { 'Showing Terraform state' }
125
172
  terraform.show({ chdir: working_dir, no_color: true }, { environment: environment })
126
173
  end
127
174
 
175
+ # Creates a new backend instance based on the OS specified in the test name. This method checks the test name
176
+ # against the valid names and versions defined by the Linux and Windows backend classes, and returns an instance
177
+ # of the appropriate class. If the test name does not match any known OS, an error is raised.
178
+ # @param test_name [String] The name of the test, which should include the OS name and version in the format
179
+ # `<prefix>_osname-version`.
180
+ # @return [CemAcpt::Provision::Linux, CemAcpt::Provision::Windows] An instance of the appropriate backend class
181
+ # based on the OS specified in the test name.
182
+ # @raise [ArgumentError] If the test name does not match any known OS or version.
128
183
  def new_backend(test_name)
129
184
  if CemAcpt::Provision::Linux.use_for?(test_name)
130
185
  logger.info('CemAcpt::Provision::Terraform') { 'Using Linux backend' }
@@ -146,6 +201,10 @@ module CemAcpt
146
201
  end
147
202
  end
148
203
 
204
+ # Creates a new environment hash for Terraform based on the provided configuration.
205
+ # @param config [CemAcpt::Config] The configuration object containing settings for the provisioner, including any
206
+ # environment variables to set when running Terraform commands.
207
+ # @return [Hash] A hash of environment variables to set when running Terraform commands.
149
208
  def new_environment(config)
150
209
  env = (config.get('terraform.environment') || {})
151
210
  env['CLOUDSDK_PYTHON_SITEPACKAGES'] = '1' # This is needed for gcloud to use numpy
@@ -153,6 +212,9 @@ module CemAcpt
153
212
  env
154
213
  end
155
214
 
215
+ # Creates a new working directory for Terraform.
216
+ # @return [String] The path to the new working directory.
217
+ # @raise [StandardError] If there is an error creating the working directory.
156
218
  def new_working_dir
157
219
  logger.debug('CemAcpt::Provision::Terraform') { 'Creating new working directory' }
158
220
  base_dir = File.join(@config.get('terraform.dir'), @config.get('platform.name'))
@@ -183,6 +245,10 @@ module CemAcpt
183
245
  raise e
184
246
  end
185
247
 
248
+ # Validates the Terraform working directory by checking that it exists and contains a Terraform file. This method
249
+ # should be called before running any Terraform commands to ensure that the working directory is properly set up.
250
+ # @raise [RuntimeError] If the working directory does not exist or does not contain a Terraform file.
251
+ # @raise [StandardError] If there is another error validating the working directory.
186
252
  def validate_working_dir!
187
253
  logger.debug('CemAcpt::Provision::Terraform') { "Validating working directory #{working_dir}" }
188
254
  logger.verbose('CemAcpt::Provision::Terraform') { "Content of #{working_dir}:\n#{Dir.glob(File.join(working_dir, '*')).join("\n")}" }
@@ -194,6 +260,11 @@ module CemAcpt
194
260
  raise e
195
261
  end
196
262
 
263
+ # Saves the given variables to a JSON file in the Terraform working directory. This file can then be used by
264
+ # Terraform to load the variables when running commands.
265
+ # @param vars [Hash] A hash of variables to save to the file. These will be converted to JSON and saved to a file
266
+ # in the working directory for use by Terraform.
267
+ # @raise [StandardError] If there is an error saving the variables to the file.
197
268
  def save_vars_to_file!(vars)
198
269
  logger.debug('CemAcpt::Provision::Terraform') { "Saving vars to file #{File.join(working_dir, DEFAULT_VARS_FILE)}" }
199
270
  File.write(File.join(working_dir, DEFAULT_VARS_FILE), vars.to_json)
@@ -201,6 +272,8 @@ module CemAcpt
201
272
  raise e
202
273
  end
203
274
 
275
+ # @return [String] The provision data for the nodes to be provisioned, formatted as a JSON string.
276
+ # @raise [StandardError] If there is an error formatting the provision data.
204
277
  def provision_node_data
205
278
  node_data = @provision_data[:nodes].each_with_object({}) do |node, h|
206
279
  h[node.node_name] = node.node_data.merge(
@@ -218,6 +291,9 @@ module CemAcpt
218
291
  raise e
219
292
  end
220
293
 
294
+ # @return [Hash] The variables to be passed to Terraform, including the provision data for the nodes and any
295
+ # necessary credentials and module package paths.
296
+ # @raise [StandardError] If there is an error formatting the variables.
221
297
  def formatted_vars
222
298
  @provision_data[:nodes].first.platform_data.merge(
223
299
  {
@@ -77,9 +77,10 @@ module CemAcpt
77
77
  # Logs a debug message to the output if it supports :debug, otherwise writes it to the output stream.
78
78
  # @param msg [String] The message to log as debug
79
79
  def debug(msg)
80
- write("DEBUG: #{msg}\n", :stderr)
81
80
  if @output.respond_to? :debug
82
81
  @output.debug(log_title) { msg }
82
+ else
83
+ write("DEBUG: #{msg}\n", :stderr)
83
84
  end
84
85
  end
85
86
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CemAcpt
4
- VERSION = '0.10.8'
4
+ VERSION = '0.10.9'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cem_acpt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.8
4
+ version: 0.10.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - puppetlabs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-02-24 00:00:00.000000000 Z
11
+ date: 2026-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http