cem_acpt 0.7.1 → 0.7.3

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