diff --git a/REFERENCE.md b/REFERENCE.md index ca10ff34..33eb4ac5 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -29,6 +29,7 @@ * [`peadm::file_or_content`](#peadm--file_or_content) * [`peadm::flatten_compact`](#peadm--flatten_compact) * [`peadm::generate_pe_conf`](#peadm--generate_pe_conf): Generate a pe.conf file in JSON format +* [`peadm::get_node_group_environment`](#peadm--get_node_group_environment): check if a custom PE environment is set in pe.conf * [`peadm::get_pe_conf`](#peadm--get_pe_conf) * [`peadm::get_targets`](#peadm--get_targets): Accept undef or a SingleTargetSpec, and return an Array[Target, 1, 0]. This differs from get_target() in that: - It returns an Array[Target * [`peadm::migration_opts_default`](#peadm--migration_opts_default) @@ -715,6 +716,24 @@ Data type: `Hash` A hash of settings to set in the config file. Any keys that are set to undef will not be included in the config file. +### `peadm::get_node_group_environment` + +Type: Puppet Language + +check if a custom PE environment is set in pe.conf + +#### `peadm::get_node_group_environment(Peadm::SingleTargetSpec $primary)` + +The peadm::get_node_group_environment function. + +Returns: `String` the desired environment for PE specific node groups + +##### `primary` + +Data type: `Peadm::SingleTargetSpec` + +the FQDN for the primary, here we will read the pe.conf from + ### `peadm::get_pe_conf` Type: Puppet Language @@ -1563,11 +1582,20 @@ The peadm::add_database class. The following parameters are available in the `peadm::add_database` plan: +* [`node_group_environment`](#-peadm--add_database--node_group_environment) * [`targets`](#-peadm--add_database--targets) * [`primary_host`](#-peadm--add_database--primary_host) * [`mode`](#-peadm--add_database--mode) * [`begin_at_step`](#-peadm--add_database--begin_at_step) +##### `node_group_environment` + +Data type: `String[1]` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production + +Default value: `peadm::get_node_group_environment($primary_host)` + ##### `targets` Data type: `Peadm::SingleTargetSpec` @@ -1692,6 +1720,7 @@ management using PEAdm. The following parameters are available in the `peadm::convert` plan: +* [`node_group_environment`](#-peadm--convert--node_group_environment) * [`primary_host`](#-peadm--convert--primary_host) * [`replica_host`](#-peadm--convert--replica_host) * [`compiler_hosts`](#-peadm--convert--compiler_hosts) @@ -1703,6 +1732,14 @@ The following parameters are available in the `peadm::convert` plan: * [`dns_alt_names`](#-peadm--convert--dns_alt_names) * [`begin_at_step`](#-peadm--convert--begin_at_step) +##### `node_group_environment` + +Data type: `String[1]` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production + +Default value: `peadm::get_node_group_environment($primary_host)` + ##### `primary_host` Data type: `Peadm::SingleTargetSpec` @@ -1805,6 +1842,7 @@ The following parameters are available in the `peadm::install` plan: * [`final_agent_state`](#-peadm--install--final_agent_state) * [`stagingdir`](#-peadm--install--stagingdir) * [`uploaddir`](#-peadm--install--uploaddir) +* [`node_group_environment`](#-peadm--install--node_group_environment) * [`primary_host`](#-peadm--install--primary_host) * [`replica_host`](#-peadm--install--replica_host) * [`compiler_hosts`](#-peadm--install--compiler_hosts) @@ -1904,6 +1942,14 @@ for offline usage. Default value: `undef` +##### `node_group_environment` + +Data type: `String[1]` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production + +Default value: `peadm::get_node_group_environment($primary_host)` + ##### `primary_host` Data type: `Peadm::SingleTargetSpec` @@ -2277,6 +2323,7 @@ The following parameters are available in the `peadm::upgrade` plan: * [`r10k_known_hosts`](#-peadm--upgrade--r10k_known_hosts) * [`stagingdir`](#-peadm--upgrade--stagingdir) * [`uploaddir`](#-peadm--upgrade--uploaddir) +* [`node_group_environment`](#-peadm--upgrade--node_group_environment) * [`primary_host`](#-peadm--upgrade--primary_host) * [`replica_host`](#-peadm--upgrade--replica_host) * [`compiler_hosts`](#-peadm--upgrade--compiler_hosts) @@ -2366,6 +2413,14 @@ for offline usage. Default value: `'/tmp'` +##### `node_group_environment` + +Data type: `String[1]` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production + +Default value: `peadm::get_node_group_environment($primary_host)` + ##### `primary_host` Data type: `Peadm::SingleTargetSpec` diff --git a/functions/get_node_group_environment.pp b/functions/get_node_group_environment.pp new file mode 100644 index 00000000..2daf3b2e --- /dev/null +++ b/functions/get_node_group_environment.pp @@ -0,0 +1,33 @@ +# +# @summary check if a custom PE environment is set in pe.conf +# +# @param primary the FQDN for the primary, here we will read the pe.conf from +# +# @return [String] the desired environment for PE specific node groups +# +# @see https://www.puppet.com/docs/pe/latest/upgrade_pe#update_environment +# +# @author Tim Meusel +# +function peadm::get_node_group_environment(Peadm::SingleTargetSpec $primary) { + $peconf = peadm::get_pe_conf(get_target($primary)) + # if both are set, they need to be set to the same value + # if they are not set, we assume that the user runs their infra in production + $pe_install = $peconf['pe_install::install::classification::pe_node_group_environment'] + $puppet_enterprise = $peconf['puppet_enterprise::master::recover_configuration::pe_environment'] + + # check if both are equal + # This also evaluates to true if both are undef + if $pe_install == $puppet_enterprise { + # check if the option isn't undef + # ToDo: A proper regex for allowed characters in an environment would be nice + # https://github.com/puppetlabs/puppet-docs/issues/1158 + if $pe_install =~ String[1] { + return $pe_install + } else { + return 'production' + } + } else { + fail("pe_install::install::classification::pe_node_group_environment and puppet_enterprise::master::recover_configuration::pe_environment need to be set to the same value, not '${pe_install}' and '${puppet_enterprise}'") + } +} diff --git a/manifests/setup/node_manager.pp b/manifests/setup/node_manager.pp index 65c69044..d2fcdbe4 100644 --- a/manifests/setup/node_manager.pp +++ b/manifests/setup/node_manager.pp @@ -23,6 +23,7 @@ # A load balancer address directing traffic to any of the "B" pool # compilers. This is used for DR configuration in large and extra large # architectures. +# @param node_group_environment the environment that will be assigned to all the PE Infra node groups # class peadm::setup::node_manager ( String[1] $primary_host, @@ -36,6 +37,7 @@ Optional[String[1]] $compiler_pool_address = undef, Optional[String[1]] $internal_compiler_a_pool_address = $server_a_host, Optional[String[1]] $internal_compiler_b_pool_address = $server_b_host, + String[1] $node_group_environment = 'production', ) { # "Not-configured" placeholder string. This will be used in places where we # cannot set an explicit null, and need to supply some kind of value. @@ -46,6 +48,7 @@ # else. Node_group { purge_behavior => none, + environment => $node_group_environment, } ################################################## diff --git a/plans/add_database.pp b/plans/add_database.pp index 6219bde8..9c0fdca5 100644 --- a/plans/add_database.pp +++ b/plans/add_database.pp @@ -1,3 +1,6 @@ +# +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# plan peadm::add_database( Peadm::SingleTargetSpec $targets, Peadm::SingleTargetSpec $primary_host, @@ -9,6 +12,7 @@ 'update-db-settings', 'cleanup-db', 'finalize']] $begin_at_step = undef, + String[1] $node_group_environment = peadm::get_node_group_environment($primary_host), ) { $primary_target = peadm::get_targets($primary_host, 1) $postgresql_target = peadm::get_targets($targets, 1) @@ -91,7 +95,7 @@ run_plan('peadm::subplans::component_install', $postgresql_target, primary_host => $primary_target, avail_group_letter => $avail_group_letter, - role => 'puppet/puppetdb-database' + role => 'puppet/puppetdb-database', ) } @@ -128,15 +132,17 @@ $host = pick($a_host, $b_host) out::verbose("In transitive state, setting classification to ${host}") run_plan('peadm::util::update_classification', $primary_target, - postgresql_a_host => $host, - postgresql_b_host => $host, - peadm_config => $peadm_config + postgresql_a_host => $host, + postgresql_b_host => $host, + peadm_config => $peadm_config, + node_group_environment => $node_group_environment, ) } else { run_plan('peadm::util::update_classification', $primary_target, - postgresql_a_host => $avail_group_letter ? { 'A' => $postgresql_host, default => undef }, - postgresql_b_host => $avail_group_letter ? { 'B' => $postgresql_host, default => undef }, - peadm_config => $peadm_config + postgresql_a_host => $avail_group_letter ? { 'A' => $postgresql_host, default => undef }, + postgresql_b_host => $avail_group_letter ? { 'B' => $postgresql_host, default => undef }, + peadm_config => $peadm_config, + node_group_environment => $node_group_environment, ) } } diff --git a/plans/add_replica.pp b/plans/add_replica.pp index 95bfb5e1..6f5afca0 100644 --- a/plans/add_replica.pp +++ b/plans/add_replica.pp @@ -9,7 +9,8 @@ # @param replica_host - The hostname and certname of the replica VM # @param replica_postgresql_host - The hostname and certname of the host with the replica PE-PosgreSQL database. # @param token_file - (optional) the token file in a different location than the default. -# +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# # Can be a separate host in an XL architecture, or undef in Standard or Large. plan peadm::add_replica( # Standard or Large @@ -21,6 +22,7 @@ # Common Configuration Optional[String] $token_file = undef, + String[1] $node_group_environment = peadm::get_node_group_environment($primary_host), ) { $primary_target = peadm::get_targets($primary_host, 1) $replica_target = peadm::get_targets($replica_host, 1) @@ -94,7 +96,8 @@ server_b_host => $replica_avail_group_letter ? { 'B' => $replica_host, default => undef }, internal_compiler_a_pool_address => $replica_avail_group_letter ? { 'A' => $replica_host, default => undef }, internal_compiler_b_pool_address => $replica_avail_group_letter ? { 'B' => $replica_host, default => undef }, - peadm_config => $peadm_config + peadm_config => $peadm_config, + node_group_environment => $node_group_environment, ) # Source list of files on Primary and synchronize to new Replica diff --git a/plans/convert.pp b/plans/convert.pp index 1995a0b0..407938fc 100644 --- a/plans/convert.pp +++ b/plans/convert.pp @@ -3,6 +3,9 @@ # This plan sets required certificate extensions on PE nodes, and configures # the required PE node groups to make an existing cluster compatible with # management using PEAdm. +# +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# plan peadm::convert ( # Standard Peadm::SingleTargetSpec $primary_host, @@ -26,6 +29,8 @@ 'modify-infra-certs', 'convert-node-groups', 'finalize']] $begin_at_step = undef, + + String[1] $node_group_environment = peadm::get_node_group_environment($primary_host), ) { peadm::assert_supported_bolt_version() @@ -223,6 +228,7 @@ compiler_pool_address => $compiler_pool_address, internal_compiler_a_pool_address => $internal_compiler_a_pool_address, internal_compiler_b_pool_address => $internal_compiler_b_pool_address, + node_group_environment => $node_group_environment, require => Class['peadm::setup::node_manager_yaml'], } diff --git a/plans/install.pp b/plans/install.pp index 4e7c9ab2..b6e4e7e4 100644 --- a/plans/install.pp +++ b/plans/install.pp @@ -31,6 +31,8 @@ # Directory the installer tarball will be uploaded to or expected to be in # for offline usage. # +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# plan peadm::install ( # Standard Peadm::SingleTargetSpec $primary_host, @@ -73,6 +75,7 @@ Enum['direct', 'bolthost'] $download_mode = 'bolthost', Boolean $permit_unsafe_versions = false, String $token_lifetime = '1y', + String[1] $node_group_environment = peadm::get_node_group_environment($primary_host), ) { peadm::assert_supported_bolt_version() @@ -134,6 +137,7 @@ internal_compiler_b_pool_address => $internal_compiler_b_pool_address, deploy_environment => $deploy_environment, ldap_config => $ldap_config, + node_group_environment => $node_group_environment, # Other stagingdir => $stagingdir, diff --git a/plans/subplans/configure.pp b/plans/subplans/configure.pp index bccc0503..49d58f9d 100644 --- a/plans/subplans/configure.pp +++ b/plans/subplans/configure.pp @@ -20,6 +20,8 @@ # Configures the state the puppet agent should be in on infrastructure nodes # after PE is configured successfully. # +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# plan peadm::subplans::configure ( # Standard Peadm::SingleTargetSpec $primary_host, @@ -42,7 +44,8 @@ # Other String $stagingdir = '/tmp', - Enum['running', 'stopped'] $final_agent_state = 'running' + Enum['running', 'stopped'] $final_agent_state = 'running', + String[1] $node_group_environment = peadm::get_node_group_environment($primary_host), ) { # TODO: get and validate PE version @@ -102,6 +105,7 @@ compiler_pool_address => $compiler_pool_address, internal_compiler_a_pool_address => $internal_compiler_a_pool_address, internal_compiler_b_pool_address => $internal_compiler_b_pool_address, + node_group_environment => $node_group_environment, require => Class['peadm::setup::node_manager_yaml'], } } diff --git a/plans/upgrade.pp b/plans/upgrade.pp index b9adcd38..8d3ef348 100644 --- a/plans/upgrade.pp +++ b/plans/upgrade.pp @@ -31,6 +31,8 @@ # Directory the installer tarball will be uploaded to or expected to be in # for offline usage. # +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# plan peadm::upgrade ( # Standard Peadm::SingleTargetSpec $primary_host, @@ -66,6 +68,7 @@ 'upgrade-replica', 'upgrade-replica-compilers', 'finalize']] $begin_at_step = undef, + String[1] $node_group_environment = peadm::get_node_group_environment($primary_host), ) { # Ensure input valid for a supported architecture $arch = peadm::assert_supported_architecture( @@ -326,6 +329,7 @@ compiler_pool_address => $compiler_pool_address, internal_compiler_a_pool_address => $internal_compiler_a_pool_address, internal_compiler_b_pool_address => $internal_compiler_b_pool_address, + node_group_environment => $node_group_environment, require => Class['peadm::setup::node_manager_yaml'], } } diff --git a/plans/util/update_classification.pp b/plans/util/update_classification.pp index 247a9632..a5018e60 100644 --- a/plans/util/update_classification.pp +++ b/plans/util/update_classification.pp @@ -2,9 +2,12 @@ # # @summary Configure classification # +# @param node_group_environment environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production +# plan peadm::util::update_classification ( # Standard Peadm::SingleTargetSpec $targets, + String[1] $node_group_environment, Optional[Hash] $peadm_config = undef, Optional[Peadm::SingleTargetSpec] $server_a_host = undef, Optional[Peadm::SingleTargetSpec] $server_b_host = undef, @@ -76,6 +79,7 @@ compiler_pool_address => $new['params']['compiler_pool_address'], internal_compiler_a_pool_address => $new['params']['internal_compiler_a_pool_address'], internal_compiler_b_pool_address => $new['params']['internal_compiler_b_pool_address'], + node_group_environment => $node_group_environment, require => Class['peadm::setup::node_manager_yaml'], } } diff --git a/spec/functions/get_node_group_environment_spec.rb b/spec/functions/get_node_group_environment_spec.rb new file mode 100644 index 00000000..bdc446c3 --- /dev/null +++ b/spec/functions/get_node_group_environment_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'peadm::get_node_group_environment' do + include BoltSpec::BoltContext + around(:each) do |example| + in_bolt_context do + example.run + end + end + let(:primary) do + ['test-vm.puppet.vm'] + end + + context 'returns production on empty pe.conf' do + it do + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) + is_expected.to run.with_params(primary).and_return('production') + end + end + + context 'returns production on non-empty pe.conf with unrelated settings' do + it do + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{"foo": true}' }) + is_expected.to run.with_params(primary).and_return('production') + end + end + context 'returns environment from pe.conf when set twice correctly' do + it do + pe = '{"pe_install::install::classification::pe_node_group_environment": "foo", "puppet_enterprise::master::recover_configuration::pe_environment": "foo"}' + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => pe }) + is_expected.to run.with_params(primary).and_return('foo') + end + end + context 'fails when both PE options are different' do + it do + pe = '{"pe_install::install::classification::pe_node_group_environment": "foo", "puppet_enterprise::master::recover_configuration::pe_environment": "bar"}' + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => pe }) + is_expected.to run.with_params(primary).and_raise_error(Puppet::PreformattedError, +%r{pe_install::install::classification::pe_node_group_environment and puppet_enterprise::master::recover_configuration::pe_environment}) + end + end +end diff --git a/spec/plans/convert_spec.rb b/spec/plans/convert_spec.rb index 7140d598..0f11af7b 100644 --- a/spec/plans/convert_spec.rb +++ b/spec/plans/convert_spec.rb @@ -19,7 +19,8 @@ allow_apply expect_task('peadm::cert_data').return_for_targets('primary' => trustedjson) - expect_task('peadm::read_file').always_return({ 'content' => '2021.7.8' }) + expect_task('peadm::read_file').with_params('path' => '/opt/puppetlabs/server/pe_version').always_return({ 'content' => '2021.7.8' }) + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) # For some reason, expect_plan() was not working?? allow_plan('peadm::modify_certificate').always_return({}) diff --git a/spec/plans/install_spec.rb b/spec/plans/install_spec.rb index 7d7b1ebb..eaf9be9f 100644 --- a/spec/plans/install_spec.rb +++ b/spec/plans/install_spec.rb @@ -7,6 +7,7 @@ it 'runs successfully with the minimum required parameters' do expect_plan('peadm::subplans::install') expect_plan('peadm::subplans::configure') + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) expect(run_plan('peadm::install', 'primary_host' => 'primary', 'console_password' => 'puppetLabs123!', 'version' => '2021.7.8')).to be_ok end end diff --git a/spec/plans/upgrade_spec.rb b/spec/plans/upgrade_spec.rb index 3943ca61..2f230cae 100644 --- a/spec/plans/upgrade_spec.rb +++ b/spec/plans/upgrade_spec.rb @@ -27,6 +27,7 @@ def allow_standard_non_returning_calls .with_params('path' => '/opt/puppetlabs/server/pe_build') .always_return({ 'content' => '2021.7.3' }) + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) expect_task('peadm::cert_data').return_for_targets('primary' => trusted_primary) expect(run_plan('peadm::upgrade', @@ -40,7 +41,7 @@ def allow_standard_non_returning_calls expect_task('peadm::read_file') .with_params('path' => '/opt/puppetlabs/server/pe_build') .always_return({ 'content' => '2021.7.3' }) - + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) expect_task('peadm::cert_data').return_for_targets('primary' => trusted_primary, 'compiler' => trusted_compiler) @@ -97,7 +98,7 @@ def allow_standard_non_returning_calls it 'updates pe.conf if r10k_known_hosts is set' do expect_task('peadm::read_file') .with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf') - .always_return({ 'content' => <<~PECONF }) + .always_return({ 'content' => <<~PECONF }).be_called_times(2) # spec pe.conf "puppet_enterprise::puppet_master_host": "%{::trusted.certname}" PECONF @@ -118,6 +119,8 @@ def allow_standard_non_returning_calls # This is fairly horrible, but expect_out_message doesn't take a regex. expect_out_message.with_params(r10k_warning) + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) + expect(run_plan('peadm::upgrade', 'primary_host' => 'primary', 'version' => '2023.3.0', @@ -130,6 +133,8 @@ def allow_standard_non_returning_calls it 'does not warn if r10k_known_hosts is not set' do expect_out_message.with_params(r10k_warning).not_be_called + expect_task('peadm::read_file').with_params('path' => '/etc/puppetlabs/enterprise/conf.d/pe.conf').always_return({ 'content' => '{}' }) + expect(run_plan('peadm::upgrade', 'primary_host' => 'primary', 'version' => '2023.4.0',