Skip to content
Snippets Groups Projects
Commit 800b7070 authored by drebs's avatar drebs
Browse files

Add Puppet ENC

This implements configuration according to hostnames:

  * `ROLE-ENV-TAG.domain`

Nodes will be thus instructed to declare the `role::${ROLE}` class
corresponding to the ${ENV} environment.

The `TAG` should be added to make sure that FQDN uniquely identifies a
node.
parent 03d50f8d
Branches enc
No related tags found
1 merge request!5Add Puppet ENC
Pipeline #53140 passed
stages:
- check-code
- compile
- tests
check-code:
image: ninfra/puppet-checker:0.0.1
......@@ -17,7 +17,7 @@ compile-profiles:
variables:
GIT_SUBMODULE_STRATEGY: recursive
USE_PUPPETDB: 'false'
stage: compile
stage: tests
script:
- 'echo "127.0.1.1 $( facter fqdn )" >> /etc/hosts'
- 'service puppet-master start'
......@@ -29,3 +29,9 @@ compile-profiles:
done < <( find ./profile/manifests/ -name "*.pp" -a -exec grep ^class "{}" \; | awk "{ print \$2 }" );'
tags:
- docker
enc-test:
image: debian:stable
stage: tests
script:
- '${CI_PROJECT_DIR}/profile/files/puppet/puppet_node_classifier --run-tests'
#!/bin/bash
#
# Puppet External Node Classifier
# -------------------------------
#
# This script parses FQDNs in the following format:
#
# ROLE-ENV-TAG.DOMAIN
#
# And returns the proper classes and environment accordingly:
#
# - ROLE should be alpha-num + '_' and the class returned will be
# role::ROLE.
#
# - ENV: should be alpha-num + '_' and, if it is a prefix of one of
# "production", "staging" or "development", then the corresponding one is
# returned as an environment for the node. Otherwise, ENV itself is
# returned.
#
# - TAG: should be alpha-num + '_' + '+' and should add enough info to make
# sure the FQDN is unique in your infrastructure.
#
# If a FQDN doesn't match as above, no special information is returned.
#
# See: https://puppet.com/docs/puppet/5.5/nodes_external.html
if [ ${#} -ne 1 ]; then
echo "Usage: ${0} NODE"
exit 1
fi
PREFIXED_ENVS='production staging development'
get_environment() {
# Return one of the PREFIXED_ENVS defined above if ENV is a prefix of
# one of them, otherwise just return ENV itself.
prefix=${1}
environment=""
for env in ${PREFIXED_ENVS}; do
if [[ ${env} == ${prefix}* ]]; then
environment=${env}
break
fi
done
if [ -z "${environment}" ]; then
environment="${prefix}"
fi
echo ${environment}
}
main() {
# Test whether the given FQDN matches ROLE-ENV-TAG.DOMAIN, and act
# accordingly.
# 1. role 2. environment 3. tag/id
regex="([[:alnum:]_]+)-([[:alnum:]_]+)-([[:alnum:]_-]+)((\.[[:alnum:]_-]+)?)+$"
fqdn=${1}
# we're only interested in matching FQDNs
if [[ ! ${fqdn} =~ ${regex} ]]; then
echo "classes:"
exit 0
fi
echo "classes:"
echo " - role::${BASH_REMATCH[1]}"
echo "environment: $( get_environment ${BASH_REMATCH[2]} )"
}
run_tests() {
# If FQDN = ROLE-ENV-TAG.DOMAIN, we expect `main` to output:
#
# ----------8<----------
# classes:
# - role::${ROLE}
# environment: ${REAL_ENV}
# ----------8<----------
#
# where REAL_ENV is either one of PREFIXED_ENVS as defined above (if
# ENV is a prefix of one of them) or just ENV otherwise.
#
# If FQDN does not fit the model, we expect just an empty `classes`
# hash:
#
# ----------8<----------
# classes:
# ----------8<----------
set -ex
# Test uses of environment prefixes.
output=$( main otherrole-prod-some-tag.example.com )
[ "${output}" == $'classes:\n - role::otherrole\nenvironment: production' ] || exit 1
output=$( main thirdrole-stag-some-tag.example.com )
[ "${output}" == $'classes:\n - role::thirdrole\nenvironment: staging' ] || exit 1
output=$( main yetanotherrole-dev-some-tag.example.com )
[ "${output}" == $'classes:\n - role::yetanotherrole\nenvironment: development' ] || exit 1
# Test uses of full environment names.
output=$( main otherrole-prod-some-tag.example.com )
[ "${output}" == $'classes:\n - role::otherrole\nenvironment: production' ] || exit 1
output=$( main thirdrole-stag-some-tag.example.com )
[ "${output}" == $'classes:\n - role::thirdrole\nenvironment: staging' ] || exit 1
output=$( main yetanotherrole-dev-some-tag.example.com )
[ "${output}" == $'classes:\n - role::yetanotherrole\nenvironment: development' ] || exit 1
# Test using an arbitrary environment
output=$( main somerole-someenv-some-tag.example.com )
[ "${output}" == $'classes:\n - role::somerole\nenvironment: someenv' ] || exit 1
# Test using something that doesn't match ROLE-ENV-TAG.DOMAIN
output=$( main arbitrary-fqdn.example.com )
[ "${output}" == $'classes:' ] || exit 1
}
if [ ${1} == '--run-tests' ]; then
run_tests
else
main ${1}
fi
......@@ -62,7 +62,7 @@ class profile::puppet::master (
server => true,
server_reports => 'store,puppetdb',
server_foreman => false,
server_external_nodes => '',
server_external_nodes => '/usr/local/bin/puppet_node_classifier',
server_git_repo => true,
server_git_repo_path => '/var/lib/gitolite3/repositories/puppet.git',
server_git_repo_user => 'gitolite3',
......@@ -183,4 +183,13 @@ class profile::puppet::master (
require => Class['puppet'],
}
# External Node Classifier
file { '/usr/local/bin/puppet_node_classifier':
ensure => file,
source => "puppet://modules/profile/puppet/puppet_node_classifier",
owner => root,
group => root,
mode => '0755';
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment