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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/cem_acpt/provision/terraform/linux.rb +7 -0
- data/lib/cem_acpt/provision/terraform/os_data.rb +33 -0
- data/lib/cem_acpt/provision/terraform/terraform_cmd.rb +102 -24
- data/lib/cem_acpt/provision/terraform.rb +77 -1
- data/lib/cem_acpt/utils/shell.rb +2 -1
- data/lib/cem_acpt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 34279d516f9561d412312959bbe0180d406a234818e4311c2238983922900de5
|
|
4
|
+
data.tar.gz: cd20359cc64580a648f74964ceb6847c7c60db987cc96dca76ab30cfd0f1a877
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb06435dc76fe50ff0dffd557db70d0e354a80093cffed96335580601e00d56dbc43a41805fb621c67177d0cf7c97d67ff33f19e90f3e871516dbcddf0661606
|
|
7
|
+
data.tar.gz: ffb32d8da0e509d56c828b2bcd356e2e0454ec138713991636881f75ed43da8dfe44f16d8d26e5c700ed0940a645d8e084842f916e5abce4b5218919f4787f91
|
data/Gemfile.lock
CHANGED
|
@@ -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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def
|
|
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
|
-
#
|
|
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
|
{
|
data/lib/cem_acpt/utils/shell.rb
CHANGED
|
@@ -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
|
|
data/lib/cem_acpt/version.rb
CHANGED
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.
|
|
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-
|
|
11
|
+
date: 2026-02-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async-http
|