cem_acpt 0.7.1 → 0.7.3

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: b51e308bc7002bf4732a8f9aba7f8a43f2a62c5af67d1f6fffc6d524da9d683f
4
- data.tar.gz: 53de22ef68903167653ac98136ed657c6c34a88adc308d4191fdfec94860b294
3
+ metadata.gz: 251ddea81d792241accdd3e63fb1b33ce655e458c08939f6da6a043cb2eeeeef
4
+ data.tar.gz: 7cf6e742a5375c190bba491e607b742263e40e15b82e68d1c383d9ca634e7b4f
5
5
  SHA512:
6
- metadata.gz: aa5189d13239222956bf6480ae2fa82513d241b88757e8dd3ef81d89bbbc576b71e1c5af3fbe01c3edf5a9ff3dc36506538be9572c3d647acf6536da8c3023c2
7
- data.tar.gz: be23f52aa2291ba5a82e60654b2aa07de3bdc262e4795447ac54b0f38ba780a669a9984fdd64cc9dd3fcaf94932f283c598af1f8e74d67a4a44ce322490b2fdd
6
+ metadata.gz: 79709f1e861e2eea1b31be633076271fefa027656dcfb8e78c252d0492286cf6376547d8756772447b28c1fe6a625cf0fee289f4a84d7e5b7e9bbfa2ef182f71
7
+ data.tar.gz: 7fc8c5351bce46273f5d57e743e1865c6d844f89fd702da451082042921cf9aae01473f90b11a3a53e810c6e2f53132de9e75d7d8d0b97c08db105c2abe172f5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cem_acpt (0.7.1)
4
+ cem_acpt (0.7.3)
5
5
  async-http (>= 0.60, < 0.70)
6
6
  bcrypt_pbkdf (>= 1.0, < 2.0)
7
7
  deep_merge (>= 1.2, < 2.0)
data/lib/cem_acpt/cli.rb CHANGED
@@ -36,15 +36,27 @@ module CemAcpt
36
36
  options[:tests] = t.split(',')
37
37
  end
38
38
  when :cem_acpt_image
39
- opts.on('-U', '--no-linux', 'Do not build Linux images') do
39
+ opts.on('--dry-run', 'Logs the information for the images that would be created. Does not create images.') do
40
+ options[:dry_run] = true
41
+ end
42
+
43
+ opts.on('--no-build-images', 'Do not build images. Can be combined with --no-destroy-nodes to just provision nodes.') do
44
+ options[:no_build_images] = true
45
+ end
46
+
47
+ opts.on('--no-linux', 'Do not build Linux images') do
40
48
  options[:cem_acpt_image] ||= {}
41
49
  options[:cem_acpt_image][:no_linux] = true
42
50
  end
43
51
 
44
- opts.on('-W', '--no-windows', 'Do not build Windows images') do
52
+ opts.on('--no-windows', 'Do not build Windows images') do
45
53
  options[:cem_acpt_image] ||= {}
46
54
  options[:cem_acpt_image][:no_windows] = true
47
55
  end
56
+
57
+ opts.on('-F', '--filter FILTER', 'Filter images to build by name with regex. Example: -F "(alma|rhel)-8"') do |f|
58
+ options[:image_name_filter] = Regexp.new(f)
59
+ end
48
60
  end
49
61
 
50
62
  opts.on('-D', '--debug', 'Enable debug logging') do
@@ -13,8 +13,9 @@ module CemAcpt
13
13
  using CemAcpt::CoreExt::ExtendedHash
14
14
 
15
15
  # Base class for other config classes
16
+ # Child classes should provide the following constant:
17
+ # - VALID_KEYS - provide an array of valid top-level keys for the config as symbols
16
18
  # Child classes should implement the following methods:
17
- # - valid_keys - provide an array of valid top-level keys for the config as symbols
18
19
  # - defaults - provide a hash of default values for the config
19
20
  # - env_var_prefix - provide a string to prefix environment variables with (defaults to 'CEM_ACPT').
20
21
  # This will be converted to uppercase, have all non-alphanumeric characters replaced with
@@ -22,6 +23,22 @@ module CemAcpt
22
23
  # variable name.
23
24
  # However, they can override any of the methods in this class.
24
25
  class Base
26
+ BASE_VALID_KEYS = %i[
27
+ ci_mode
28
+ config_file
29
+ log_level
30
+ log_file
31
+ log_format
32
+ no_destroy_nodes
33
+ no_ephemeral_ssh_key
34
+ platform
35
+ provisioner
36
+ quiet
37
+ terraform
38
+ user_config
39
+ verbose
40
+ ].freeze
41
+
25
42
  attr_reader :config, :env_vars
26
43
 
27
44
  def initialize(opts: {}, config_file: nil, load_user_config: true)
@@ -36,7 +53,11 @@ module CemAcpt
36
53
 
37
54
  # @return [Array<Symbol>] Valid top-level keys for the config
38
55
  def valid_keys
39
- []
56
+ if self.class.const_defined?(:VALID_KEYS)
57
+ (BASE_VALID_KEYS + self.class.const_get(:VALID_KEYS)).uniq
58
+ else
59
+ BASE_VALID_KEYS
60
+ end
40
61
  end
41
62
 
42
63
  # @return [Hash] The default configuration
@@ -8,30 +8,13 @@ module CemAcpt
8
8
  class CemAcpt < Base
9
9
  VALID_KEYS = %i[
10
10
  actions
11
- ci_mode
12
- config_file
13
11
  image_name_builder
14
- log_level
15
- log_file
16
- log_format
17
12
  module_dir
18
13
  node_data
19
- no_destroy_nodes
20
- no_ephemeral_ssh_key
21
- platform
22
- provisioner
23
- quiet
24
- terraform
25
14
  test_data
26
15
  tests
27
- user_config
28
- verbose
29
16
  ].freeze
30
17
 
31
- def valid_keys
32
- VALID_KEYS
33
- end
34
-
35
18
  # The default configuration
36
19
  def defaults
37
20
  {
@@ -7,26 +7,13 @@ module CemAcpt
7
7
  # Holds the configuration for cem_acpt_image
8
8
  class CemAcptImage < Base
9
9
  VALID_KEYS = %i[
10
- ci_mode
11
- config_file
10
+ cem_acpt_image
11
+ dry_run
12
12
  images
13
- log_level
14
- log_file
15
- log_format
16
- no_destroy_nodes
17
- no_ephemeral_ssh_key
18
- platform
19
- provisioner
20
- quiet
21
- terraform
22
- user_config
23
- verbose
13
+ image_name_filter
14
+ no_build_images
24
15
  ].freeze
25
16
 
26
- def valid_keys
27
- VALID_KEYS
28
- end
29
-
30
17
  def env_var_prefix
31
18
  'CEM_ACPT_IMAGE'
32
19
  end
@@ -34,12 +21,19 @@ module CemAcpt
34
21
  # The default configuration
35
22
  def defaults
36
23
  {
24
+ cem_acpt_image: {
25
+ no_linux: false,
26
+ no_windows: false,
27
+ },
37
28
  ci_mode: false,
38
29
  config_file: nil,
30
+ dry_run: false,
39
31
  images: {},
32
+ image_name_filter: Regexp.new('.*'),
40
33
  log_level: 'info',
41
34
  log_file: nil,
42
35
  log_format: 'text',
36
+ no_destroy_nodes: false,
43
37
  no_ephemeral_ssh_key: false,
44
38
  platform: {
45
39
  name: 'gcp',
@@ -80,6 +80,7 @@ module CemAcpt
80
80
  'centos' => 'EnterpriseLinuxFamily',
81
81
  'rhel' => 'EnterpriseLinuxFamily',
82
82
  'alma' => 'EnterpriseLinuxFamily',
83
+ 'oel' => 'EnterpriseLinuxFamily',
83
84
  'windows' => 'WindowsFamily',
84
85
  }.freeze
85
86
 
@@ -14,7 +14,17 @@ module CemAcpt
14
14
  # This module contains the classes and methods for building test node images
15
15
  module ImageBuilder
16
16
  def self.build_images(config)
17
- TerraformBuilder.new(config).run
17
+ include CemAcpt::Logging
18
+
19
+ builder = TerraformBuilder.new(config)
20
+ builder.run
21
+ logger.info('ImageBuilder') { "Image builder finished after #{builder.duration} seconds" }
22
+ if builder.exit_code.zero?
23
+ logger.info('ImageBuilder') { 'Image builder finished successfully' }
24
+ else
25
+ logger.error('ImageBuilder') { "Image builder finished with exit code #{builder.exit_code}" }
26
+ end
27
+ exit builder.exit_code
18
28
  end
19
29
 
20
30
  # This class builds test node images using Terraform
@@ -27,6 +37,8 @@ module CemAcpt
27
37
  DEFAULT_VARS_FILE = 'imagevars.json'
28
38
  include CemAcpt::Logging
29
39
 
40
+ attr_reader :exit_code, :duration
41
+
30
42
  def initialize(config)
31
43
  @config = config
32
44
  @image_terraform_dir = File.join(config.get('terraform.dir'), 'image', config.get('platform.name'))
@@ -36,7 +48,7 @@ module CemAcpt
36
48
  @linux_tfvars = { node_data: {} }
37
49
  @windows_tfvars = { node_data: {} }
38
50
  @duration = 0
39
- @exit_code = 0
51
+ @exit_code = 1
40
52
  @private_key = nil
41
53
  @public_key = nil
42
54
  end
@@ -44,17 +56,19 @@ module CemAcpt
44
56
  def run
45
57
  @start_time = Time.now
46
58
  logger.with_ci_group("CemAcptImage v#{CemAcpt::VERSION} run started at #{@start_time}") do
47
- logger.info('CemAcptImage') { "Using working directory: #{@working_dir}..." }
48
- keep_terminal_alive
49
59
  @all_tfvars = new_tfvars(@config)
50
- @working_dir = new_working_dir
51
60
  @linux_tfvars, @windows_tfvars = divide_tfvars_by_os(@all_tfvars)
52
- save_vars_to_file!('linux', @linux_tfvars)
53
- save_vars_to_file!('windows', @windows_tfvars)
54
- terraform_init
55
61
  image_types = []
56
62
  image_types << [@linux_tfvars, 'linux'] unless no_linux?
57
63
  image_types << [@windows_tfvars, 'windows'] unless no_windows?
64
+ return dry_run(image_types) if @config.get('dry_run')
65
+
66
+ @working_dir = new_working_dir
67
+ logger.info('CemAcptImage') { "Using working directory: #{@working_dir}..." }
68
+ keep_terminal_alive
69
+ save_vars_to_file!('linux', @linux_tfvars)
70
+ save_vars_to_file!('windows', @windows_tfvars)
71
+ terraform_init
58
72
  image_types.each do |tfvars, os_str|
59
73
  terraform_plan(os_str, tfvars, DEFAULT_PLAN_NAME)
60
74
  begin
@@ -63,14 +77,27 @@ module CemAcpt
63
77
  output.each do |instance_name, data|
64
78
  logger.info('CemAcptImage') { "Stopping instance #{instance_name}..." }
65
79
  @exec.run('compute', 'instances', 'stop', instance_name)
66
- deprecate_old_images_in_family(data['image_family'])
67
- create_image_from_disk(data['disk_link'], image_name_from_image_family(data['image_family']), data['image_family'])
80
+ unless @config.get('no_build_images')
81
+ deprecate_old_images_in_family(data['image_family'])
82
+ create_image_from_disk(data['disk_link'], image_name_from_image_family(data['image_family']), data['image_family'])
83
+ end
84
+ @exit_code = 0
68
85
  end
69
86
  ensure
70
- terraform_destroy(os_str, tfvars)
87
+ terraform_destroy(os_str, tfvars) unless @config.get('no_destroy_nodes')
71
88
  end
72
89
  end
73
90
  end
91
+ rescue StandardError => e
92
+ logger.error('CemAcptImage') { "Image builder failed with error: #{e}" }
93
+ logger.verbose('CemAcptImage') { e.backtrace.join("\n") }
94
+ @exit_code = 1
95
+ ensure
96
+ if @start_time
97
+ @duration = Time.now - @start_time
98
+ else
99
+ @duration = 0
100
+ end
74
101
  end
75
102
 
76
103
  private
@@ -107,6 +134,15 @@ module CemAcpt
107
134
  @linux_tfvars[:node_data].empty? || @config.get('cem_acpt_image.no_linux')
108
135
  end
109
136
 
137
+ def dry_run(image_types)
138
+ logger.info('CemAcptImage') { 'Dry run mode enabled. No images will be built.' }
139
+ image_types.each do |tfvars, os_str|
140
+ logger.info('CemAcptImage') { "Dry run for #{os_str}..." }
141
+ logger.info('CemAcptImage') { "Terraform vars:\n#{JSON.pretty_generate(tfvars)}" }
142
+ end
143
+ @exit_code = 0
144
+ end
145
+
110
146
  def terraform
111
147
  return @terraform if defined?(@terraform)
112
148
 
@@ -233,6 +269,8 @@ module CemAcpt
233
269
  tfvars[:private_key] = private_key if private_key
234
270
  tfvars[:public_key] = public_key if public_key
235
271
  config.get('images').each do |image_name, image|
272
+ next if config.get('image_name_filter')&.respond_to?(:match?) && !config.get('image_name_filter').match?(image_name)
273
+
236
274
  platform = new_platform(config, **tfvars)
237
275
  tfvars.merge!(platform.platform_data)
238
276
  provision_commands = CemAcpt::ImageBuilder::ProvisionCommands.provision_commands(
@@ -40,7 +40,23 @@ module CemAcpt
40
40
  commands << "sudo systemctl start #{file} && sudo systemctl enable #{file}"
41
41
  end
42
42
  end
43
- commands << "sudo #{puppet_bin_path} apply #{destination_provision_directory}/#{puppet_manifest_file}"
43
+ commands << apply_command
44
+ end
45
+
46
+ private
47
+
48
+ def apply_command
49
+ cmd = [
50
+ 'sudo',
51
+ puppet_bin_path,
52
+ 'apply',
53
+ '--logdest',
54
+ 'console,/opt/cem_acpt/provision_apply.log',
55
+ ]
56
+ cmd << '--debug' if @config.debug?
57
+ cmd << '--verbose' if @config.verbose?
58
+ cmd << "#{destination_provision_directory}/#{puppet_manifest_file}"
59
+ cmd.join(' ')
44
60
  end
45
61
  end
46
62
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CemAcpt
4
- VERSION = '0.7.1'
4
+ VERSION = '0.7.3'
5
5
  end
@@ -1,9 +1,9 @@
1
1
  command:
2
2
  puppet_idempotent:
3
- exec: 'sudo /opt/puppetlabs/puppet/bin/puppet apply --verbose --detailed-exitcodes /opt/cem_acpt/manifest.pp'
3
+ exec: 'sudo /opt/puppetlabs/puppet/bin/puppet apply --logdest console,/opt/cem_acpt/idempotent_apply.log --debug --verbose --detailed-exitcodes /opt/cem_acpt/manifest.pp'
4
4
  timeout: 300000 # 5 mins in miliseconds
5
5
  stdout:
6
- - "Applied catalog in"
6
+ - "/Applied catalog in.*/"
7
7
  stderr:
8
8
  - ""
9
9
  exit-status: 0
@@ -1,6 +1,6 @@
1
1
  command:
2
2
  puppet_noop:
3
- exec: 'sudo /opt/puppetlabs/puppet/bin/puppet apply --verbose --detailed-exitcodes --noop /opt/cem_acpt/manifest.pp'
3
+ exec: 'sudo /opt/puppetlabs/puppet/bin/puppet apply --logdest console,/opt/cem_acpt/noop_apply.log --debug --verbose --detailed-exitcodes --noop /opt/cem_acpt/manifest.pp'
4
4
  timeout: 300000 # 5 mins in miliseconds
5
5
  stdout:
6
6
  - "Applied catalog in"
@@ -0,0 +1,9 @@
1
+ command:
2
+ puppet_idempotent:
3
+ exec: 'C:\Program Files\Puppet Labs\Puppet\bin\puppet apply --verbose --detailed-exitcodes C:\cem_acpt\manifest.pp'
4
+ timeout: 300000 # 5 mins in miliseconds
5
+ stdout:
6
+ - "Applied catalog in"
7
+ stderr:
8
+ - ""
9
+ exit-status: 0
@@ -0,0 +1,12 @@
1
+ command:
2
+ puppet_noop:
3
+ exec: 'C:\Program Files\Puppet Labs\Puppet\bin\puppet apply --verbose --detailed-exitcodes --noop C:\cem_acpt\manifest.pp'
4
+ timeout: 300000 # 5 mins in miliseconds
5
+ stdout:
6
+ - "Applied catalog in"
7
+ stderr:
8
+ - ""
9
+ exit-status:
10
+ or:
11
+ - 0
12
+ - 2
@@ -0,0 +1,89 @@
1
+ terraform {
2
+ required_providers {
3
+ google = {
4
+ source = "hashicorp/google"
5
+ version = "4.59.0"
6
+ }
7
+ }
8
+ }
9
+
10
+ variable "credentials_file" {
11
+ type = string
12
+ }
13
+
14
+ variable "project" {
15
+ type = string
16
+ }
17
+
18
+ variable "region" {
19
+ type = string
20
+ }
21
+
22
+ variable "zone" {
23
+ type = string
24
+ }
25
+
26
+ variable "subnetwork" {
27
+ type = string
28
+ }
29
+
30
+ variable "node_data" {
31
+ type = map(object({
32
+ machine_type = string
33
+ image = string
34
+ disk_size = number
35
+ test_name = string
36
+ }))
37
+ }
38
+
39
+ provider "google" {
40
+ credentials = file(var.credentials_file)
41
+ project = var.project
42
+ region = var.region
43
+ zone = var.zone
44
+ }
45
+
46
+ resource "google_compute_instance" "acpt-test-node" {
47
+ provider = google
48
+ for_each = var.node_data
49
+ name = each.key
50
+ machine_type = each.value.machine_type
51
+
52
+ boot_disk {
53
+ initialize_params {
54
+ image = each.value.image
55
+ size = each.value.disk_size
56
+ type = "pd-standard"
57
+ }
58
+ }
59
+
60
+ scheduling {
61
+ preemptible = true
62
+ automatic_restart = false
63
+ provisioning_model = "SPOT"
64
+ instance_termination_action = "DELETE"
65
+ }
66
+
67
+ network_interface {
68
+ subnetwork = var.subnetwork
69
+ access_config {
70
+ network_tier = "STANDARD"
71
+ }
72
+ }
73
+
74
+ metadata = {
75
+ "enable-oslogin" = "TRUE"
76
+ "cem-acpt-test" = each.value.test_name
77
+ }
78
+
79
+ tags = [ "cem-acpt-test-node" ]
80
+ }
81
+
82
+ output "instance_name_ip" {
83
+ value = {
84
+ for k, v in google_compute_instance.acpt-test-node : v.name => {
85
+ ip = v.network_interface.0.access_config.0.nat_ip,
86
+ test_name = v.metadata.cem-acpt-test,
87
+ }
88
+ }
89
+ }
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.7.1
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - puppetlabs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-17 00:00:00.000000000 Z
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http
@@ -210,6 +210,9 @@ files:
210
210
  - lib/terraform/gcp/linux/systemd/goss-idempotent.service
211
211
  - lib/terraform/gcp/linux/systemd/goss-noop.service
212
212
  - lib/terraform/gcp/windows/.keep
213
+ - lib/terraform/gcp/windows/goss/puppet_idempotent.yaml
214
+ - lib/terraform/gcp/windows/goss/puppet_noop.yaml
215
+ - lib/terraform/gcp/windows/main.tf
213
216
  - lib/terraform/image/gcp/linux/main.tf
214
217
  - lib/terraform/image/gcp/windows/.keep
215
218
  - sample_config.yaml