From 119a48b54bedddea9b044375297d6fc466ada5f9 Mon Sep 17 00:00:00 2001 From: Tim Meusel Date: Mon, 19 Aug 2024 21:47:29 +0200 Subject: [PATCH] (#469) Assign correct environment to node groups This checks if a user configured a environment in pe.conf. If that's the case, it will be used for the PEADM-specific node groups. Otherwise we fall back to production. This fixes a timing issue discovered in #469. In situations where the PE infra isn't running in production, we cannot assume that a production environment exists. And a node group can only reference classes from the environment the node group belongs to. --- REFERENCE.md | 76 ++++++++++++++++++++++++- functions/get_node_group_environment.pp | 31 ++++++++++ manifests/setup/node_manager.pp | 3 + plans/add_database.pp | 22 ++++--- plans/add_replica.pp | 8 ++- plans/convert.pp | 6 ++ plans/install.pp | 4 ++ plans/subplans/configure.pp | 4 ++ plans/upgrade.pp | 4 ++ plans/util/update_classification.pp | 4 ++ spec/plans/convert_spec.rb | 3 +- 11 files changed, 153 insertions(+), 12 deletions(-) create mode 100644 functions/get_node_group_environment.pp diff --git a/REFERENCE.md b/REFERENCE.md index ca10ff34..61b839eb 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) @@ -109,7 +110,6 @@ Supported use cases: * `peadm::misc::divert_code_manager`: This plan exists to account for a scenario where a PE XL * `peadm::modify_cert_extensions` * `peadm::subplans::component_install`: Install a new PEADM component -* `peadm::subplans::configure`: Configure first-time classification and DR setup * `peadm::subplans::db_populate`: Destructively (re)populates a new or existing database with the contents or a known good source * `peadm::subplans::install`: Perform initial installation of Puppet Enterprise Extra Large * `peadm::subplans::modify_certificate` @@ -715,6 +715,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(Target $primary)` + +The peadm::get_node_group_environment function. + +Returns: `Any` + +##### `primary` + +Data type: `Target` + +the FQDN for the primary, here we will read the pe.conf from + ### `peadm::get_pe_conf` Type: Puppet Language @@ -1563,10 +1581,16 @@ 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) +* [`environment_node_group`](#-peadm--add_database--environment_node_group) + +##### `node_group_environment` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production ##### `targets` @@ -1606,6 +1630,14 @@ Optional[Enum[ Default value: `undef` +##### `environment_node_group` + +Data type: `String[1]` + + + +Default value: `peadm::get_node_group_environment($primary_host)` + ### `peadm::backup` Backup puppet primary configuration @@ -1692,6 +1724,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) @@ -1702,6 +1735,11 @@ The following parameters are available in the `peadm::convert` plan: * [`internal_compiler_b_pool_address`](#-peadm--convert--internal_compiler_b_pool_address) * [`dns_alt_names`](#-peadm--convert--dns_alt_names) * [`begin_at_step`](#-peadm--convert--begin_at_step) +* [`environment_node_group`](#-peadm--convert--environment_node_group) + +##### `node_group_environment` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production ##### `primary_host` @@ -1789,6 +1827,14 @@ Optional[Enum[ Default value: `undef` +##### `environment_node_group` + +Data type: `String[1]` + + + +Default value: `peadm::get_node_group_environment($primary_host)` + ### `peadm::install` Install a new PE cluster @@ -1805,6 +1851,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) @@ -1825,6 +1872,7 @@ The following parameters are available in the `peadm::install` plan: * [`download_mode`](#-peadm--install--download_mode) * [`permit_unsafe_versions`](#-peadm--install--permit_unsafe_versions) * [`token_lifetime`](#-peadm--install--token_lifetime) +* [`environment_node_group`](#-peadm--install--environment_node_group) ##### `compiler_pool_address` @@ -1904,6 +1952,10 @@ for offline usage. Default value: `undef` +##### `node_group_environment` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production + ##### `primary_host` Data type: `Peadm::SingleTargetSpec` @@ -2060,6 +2112,14 @@ Data type: `String` Default value: `'1y'` +##### `environment_node_group` + +Data type: `String[1]` + + + +Default value: `peadm::get_node_group_environment($primary_host)` + ### `peadm::modify_certificate` Certificates can be modified by adding extensions, removing extensions, or @@ -2277,6 +2337,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) @@ -2287,6 +2348,7 @@ The following parameters are available in the `peadm::upgrade` plan: * [`download_mode`](#-peadm--upgrade--download_mode) * [`permit_unsafe_versions`](#-peadm--upgrade--permit_unsafe_versions) * [`begin_at_step`](#-peadm--upgrade--begin_at_step) +* [`environment_node_group`](#-peadm--upgrade--environment_node_group) ##### `compiler_pool_address` @@ -2366,6 +2428,10 @@ for offline usage. Default value: `'/tmp'` +##### `node_group_environment` + +environment for the PEADM specific node groups, if not set it will be gathered from pe.conf or production + ##### `primary_host` Data type: `Peadm::SingleTargetSpec` @@ -2454,6 +2520,14 @@ Optional[Enum[ Default value: `undef` +##### `environment_node_group` + +Data type: `String[1]` + + + +Default value: `peadm::get_node_group_environment($primary_host)` + ### `peadm::util::init_db_server` The peadm::util::init_db_server class. diff --git a/functions/get_node_group_environment.pp b/functions/get_node_group_environment.pp new file mode 100644 index 00000000..daa2a8dd --- /dev/null +++ b/functions/get_node_group_environment.pp @@ -0,0 +1,31 @@ +# +# @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 +# +# @see https://www.puppet.com/docs/pe/latest/upgrade_pe#update_environment +# +# @author Tim Meusel +# +function peadm::get_node_group_environment(Target $primary) { + $peconf = peadm::get_pe_conf($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..01b0aee0 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] $environment_node_group = peadm::get_node_group_environment($primary_host), ) { $primary_target = peadm::get_targets($primary_host, 1) $postgresql_target = peadm::get_targets($targets, 1) @@ -91,13 +95,13 @@ 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', ) } # Stop Puppet to ensure catalogs are not being compiled for PE infrastructure nodes run_command('systemctl stop puppet.service', peadm::flatten_compact([ - $postgresql_target, + $postgresql_target, $compilers, $primary_target, $replica_target, @@ -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, + environment_node_group => $environment_node_group, ) } 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, + environment_node_group => $environment_node_group, ) } } diff --git a/plans/add_replica.pp b/plans/add_replica.pp index 95bfb5e1..2395b6d3 100644 --- a/plans/add_replica.pp +++ b/plans/add_replica.pp @@ -9,7 +9,9 @@ # @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 +23,7 @@ # Common Configuration Optional[String] $token_file = undef, + String[1] $environment_node_group = 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 +97,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, + environment_node_group => $environment_node_group, ) # Source list of files on Primary and synchronize to new Replica diff --git a/plans/convert.pp b/plans/convert.pp index 1995a0b0..6c40ac35 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] $environment_node_group = 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..39a3e1f3 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] $environment_node_group = 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, + environment_node_group => $environment_node_group, # Other stagingdir => $stagingdir, diff --git a/plans/subplans/configure.pp b/plans/subplans/configure.pp index bccc0503..4e9bd503 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, @@ -43,6 +45,7 @@ # Other String $stagingdir = '/tmp', Enum['running', 'stopped'] $final_agent_state = 'running' + String[1] $environment_node_group = 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, + environment_node_group => $environment_node_group, require => Class['peadm::setup::node_manager_yaml'], } } diff --git a/plans/upgrade.pp b/plans/upgrade.pp index b9adcd38..456e98fa 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] $environment_node_group = 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, + environment_node_group => $environment_node_group, require => Class['peadm::setup::node_manager_yaml'], } } diff --git a/plans/util/update_classification.pp b/plans/util/update_classification.pp index 247a9632..a59bf04d 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] $environment_node_group, 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'], + environment_node_group => $environment_node_group, require => Class['peadm::setup::node_manager_yaml'], } } diff --git a/spec/plans/convert_spec.rb b/spec/plans/convert_spec.rb index 7140d598..23c8572f 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_build').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({})