Merge branch 'develop' into neoloc/grafana
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# arpa_fact.rb
|
||||
|
||||
require 'facter'
|
||||
|
||||
Facter.add(:arpa) do
|
||||
setcode do
|
||||
arpa_info = {}
|
||||
Facter.value(:networking)['interfaces'].each do |interface_name, values|
|
||||
next unless values.key?('ip')
|
||||
|
||||
ip_address = values['ip']
|
||||
reversed_ip_parts = ip_address.split('.').reverse
|
||||
addr = "#{reversed_ip_parts.join('.')}.in-addr.arpa"
|
||||
|
||||
trimmed_ip_parts = reversed_ip_parts[1..]
|
||||
zone = "#{trimmed_ip_parts.join('.')}.in-addr.arpa"
|
||||
|
||||
arpa_info[interface_name] = {
|
||||
'zone' => zone,
|
||||
'addr' => addr
|
||||
}
|
||||
end
|
||||
arpa_info
|
||||
end
|
||||
end
|
||||
@@ -1,14 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# create an enc_role_path fact from enc_role, to be used by hiera.yaml
|
||||
#
|
||||
# roles::infra::dns::resolver becomes roles/infra/dns/resolver
|
||||
Facter.add(:enc_role_path) do
|
||||
setcode do
|
||||
enc_role = Facter.value(:enc_role)
|
||||
if enc_role
|
||||
enc_role_path = enc_role.gsub('::', '/')
|
||||
enc_role_path
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# split the enc_role fact into different tiers
|
||||
#
|
||||
# e.g.
|
||||
# enc_role_tier2: roles::infra::dns::resolver -> infra
|
||||
Facter.add(:enc_role_tier1) do
|
||||
setcode do
|
||||
role = Facter.value(:enc_role)
|
||||
if role
|
||||
parts = role.split('::')
|
||||
parts[1] if parts.size > 1
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,14 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# split the enc_role fact into different tiers
|
||||
# e.g.
|
||||
# enc_role_tier2: roles::infra::dns::resolver -> dns
|
||||
Facter.add(:enc_role_tier2) do
|
||||
setcode do
|
||||
role = Facter.value(:enc_role)
|
||||
if role
|
||||
parts = role.split('::')
|
||||
parts[2] if parts.size > 2
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,14 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# split the enc_role fact into different tiers
|
||||
# e.g.
|
||||
# enc_role_tier3: roles::infra::dns::resolver -> resolver
|
||||
Facter.add(:enc_role_tier3) do
|
||||
setcode do
|
||||
role = Facter.value(:enc_role)
|
||||
if role
|
||||
parts = role.split('::')
|
||||
parts[3] if parts.size > 3
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# create a boolean for when the mariadb service is active
|
||||
require 'English'
|
||||
|
||||
Facter.add('mariadb_active') do
|
||||
setcode do
|
||||
system('systemctl is-active --quiet mariadb')
|
||||
$CHILD_STATUS.exitstatus.zero?
|
||||
end
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# check if the /etc/my.cnf.d/server.cnf file exists,
|
||||
# open it and search for the 'datadir =' option
|
||||
# store the datadir value as this fact
|
||||
require 'facter'
|
||||
|
||||
Facter.add('mariadb_datapath') do
|
||||
setcode do
|
||||
if File.exist?('/etc/my.cnf.d/server.cnf')
|
||||
datadir = nil
|
||||
File.foreach('/etc/my.cnf.d/server.cnf') do |line|
|
||||
match = line.match(/^\s*datadir\s*=\s*(.+)\s*$/)
|
||||
if match
|
||||
datadir = match[1].strip
|
||||
break
|
||||
end
|
||||
end
|
||||
datadir
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# check if the mariadb server exists
|
||||
# check if the mariadb_datapath fact exists, else set /var/lib/mysql as the datapath
|
||||
# check if the galera grastate.dat file exists, identifying if galera is boostrapped
|
||||
require 'facter'
|
||||
|
||||
if system('systemctl is-active --quiet mariadb')
|
||||
|
||||
Facter.add('mariadb_galera_active') do
|
||||
setcode do
|
||||
mariadb_datapath = Facter.value(:mariadb_datapath) || '/var/lib/mysql'
|
||||
File.exist?("#{mariadb_datapath}/grastate.dat")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# create boolean for if mariadb is installed based of the default service file
|
||||
Facter.add('mariadb_installed') do
|
||||
setcode do
|
||||
File.exist?('/usr/lib/systemd/system/mariadb.service')
|
||||
end
|
||||
end
|
||||
@@ -1,21 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# skip if mysql isnt installed or active
|
||||
if system('which mysql > /dev/null 2>&1') && system('systemctl is-active --quiet mariadb')
|
||||
|
||||
# export mysql wsrep status
|
||||
wsrep_status = `mysql -e "SHOW STATUS LIKE 'wsrep%';"`
|
||||
|
||||
# loop over the output
|
||||
wsrep_status.each_line do |line|
|
||||
# skip the line unless it starts with 'wsrep_'
|
||||
next unless line.match(/^wsrep_/)
|
||||
|
||||
key, value = line.split("\t")
|
||||
Facter.add("mysql_#{key.strip}") do
|
||||
setcode do
|
||||
value.strip
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,15 +1,16 @@
|
||||
# create the sysadmin user
|
||||
class profiles::accounts::sysadmin(
|
||||
String $password,
|
||||
Array[String] $sshkeys = [],
|
||||
){
|
||||
profiles::base::account {'sysadmin':
|
||||
username => 'sysadmin',
|
||||
uid => 1000,
|
||||
gid => 1000,
|
||||
groups => ['wheel'],
|
||||
sshkeys => $sshkeys,
|
||||
sudo_rules => ['sysadmin ALL=(ALL) NOPASSWD:ALL'],
|
||||
password => '',
|
||||
ignore_pass => true,
|
||||
username => 'sysadmin',
|
||||
uid => 1000,
|
||||
gid => 1000,
|
||||
groups => ['adm', 'admins', 'systemd-journal'],
|
||||
sshkeys => $sshkeys,
|
||||
sudo_rules => ['sysadmin ALL=(ALL) NOPASSWD:ALL'],
|
||||
password => $password,
|
||||
require => Group['admins'],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,27 +30,17 @@ class profiles::apt::puppet7 (
|
||||
Array[String] $managed_repos,
|
||||
String $mirror,
|
||||
String $repo,
|
||||
String $dist,
|
||||
) {
|
||||
|
||||
$codename = $facts['os']['distro']['codename']
|
||||
|
||||
if 'puppet7' in $managed_repos {
|
||||
$puppet_source = "${mirror}/${repo}-release-${dist}.deb"
|
||||
|
||||
# Install the puppet release using dpkg
|
||||
package { "${repo}-${dist}":
|
||||
ensure => installed,
|
||||
name => "${repo}-release",
|
||||
provider => dpkg,
|
||||
source => $puppet_source,
|
||||
}
|
||||
|
||||
# deb http://apt.puppet.com bullseye puppet7
|
||||
apt::source { 'puppet7':
|
||||
location => $mirror,
|
||||
repos => $repo,
|
||||
release => $dist,
|
||||
release => $codename,
|
||||
include => {
|
||||
'src' => false,
|
||||
'deb' => true,
|
||||
|
||||
@@ -3,55 +3,64 @@ class profiles::base (
|
||||
Array $puppet_servers,
|
||||
) {
|
||||
|
||||
case $facts['os']['family'] {
|
||||
'RedHat': {
|
||||
include profiles::yum::global
|
||||
include profiles::firewall::firewalld
|
||||
# run a limited set of classes on the first run aimed at bootstrapping the new node
|
||||
if $facts['firstrun'] {
|
||||
include profiles::firstrun::init
|
||||
}else{
|
||||
|
||||
# install the vault ca first
|
||||
include profiles::pki::vaultca
|
||||
|
||||
# manage the puppet agent
|
||||
include profiles::puppet::agent
|
||||
|
||||
# manage puppet clients
|
||||
if ! member($puppet_servers, $trusted['certname']) {
|
||||
include profiles::puppet::client
|
||||
}
|
||||
'Debian': {
|
||||
include profiles::apt::global
|
||||
|
||||
# include the base profiles
|
||||
include profiles::base::repos
|
||||
include profiles::packages
|
||||
include profiles::base::facts
|
||||
include profiles::base::motd
|
||||
include profiles::base::scripts
|
||||
include profiles::base::hosts
|
||||
include profiles::base::groups
|
||||
include profiles::base::root
|
||||
include profiles::accounts::sysadmin
|
||||
include profiles::ntp::client
|
||||
include profiles::dns::base
|
||||
include profiles::pki::vault
|
||||
include profiles::cloudinit::init
|
||||
include profiles::metrics::default
|
||||
include profiles::helpers::node_lookup
|
||||
include profiles::consul::client
|
||||
|
||||
# include the python class
|
||||
class { 'python':
|
||||
manage_python_package => true,
|
||||
manage_venv_package => true,
|
||||
manage_pip_package => true,
|
||||
use_epel => false,
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported OS family ${facts['os']['family']}")
|
||||
|
||||
# all hosts will have sudo applied
|
||||
class { 'sudo':
|
||||
secure_path => '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/opt/puppetlabs/bin'
|
||||
}
|
||||
}
|
||||
|
||||
# manage the puppet agent
|
||||
include profiles::puppet::agent
|
||||
# manage virtualised guest agents
|
||||
if $::facts['is_virtual'] and $::facts['dmi']['manufacturer'] == 'QEMU' {
|
||||
include profiles::qemu::agent
|
||||
}
|
||||
|
||||
# manage puppet clients
|
||||
if ! member($puppet_servers, $trusted['certname']) {
|
||||
include profiles::puppet::client
|
||||
}
|
||||
# include classes from hiera
|
||||
lookup('hiera_classes', Array[String], 'unique').include
|
||||
|
||||
# include the base profiles
|
||||
include profiles::packages::base
|
||||
include profiles::base::facts
|
||||
include profiles::base::motd
|
||||
include profiles::base::scripts
|
||||
include profiles::base::hosts
|
||||
include profiles::accounts::sysadmin
|
||||
include profiles::ntp::client
|
||||
include profiles::dns::base
|
||||
include profiles::cloudinit::init
|
||||
include profiles::metrics::default
|
||||
include profiles::helpers::node_lookup
|
||||
|
||||
# include the python class
|
||||
class { 'python':
|
||||
manage_python_package => true,
|
||||
manage_venv_package => true,
|
||||
manage_pip_package => true,
|
||||
use_epel => false,
|
||||
}
|
||||
|
||||
# all hosts will have sudo applied
|
||||
class { 'sudo':
|
||||
secure_path => '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/opt/puppetlabs/bin'
|
||||
}
|
||||
|
||||
# manage virtualised guest agents
|
||||
if $::facts['is_virtual'] and $::facts['dmi']['manufacturer'] == 'QEMU' {
|
||||
include profiles::qemu::agent
|
||||
# specifc ordering constraints
|
||||
Class['profiles::pki::vaultca']
|
||||
-> Class['profiles::base::repos']
|
||||
-> Class['profiles::packages']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#
|
||||
class profiles::base::datavol (
|
||||
Enum['present', 'absent'] $ensure = 'present',
|
||||
Enum['present', 'absent', 'mounted'] $mountstate = 'mounted',
|
||||
Enum['ext2', 'ext3', 'ext4', 'xfs', 'btrfs'] $fstype = 'xfs',
|
||||
String $vg = 'datavg',
|
||||
String $pv = '/dev/vdb',
|
||||
@@ -63,7 +64,7 @@ class profiles::base::datavol (
|
||||
|
||||
# Ensure the logical volume is mounted at the desired location
|
||||
mount { $mount:
|
||||
ensure => $ensure,
|
||||
ensure => $mountstate,
|
||||
device => "/dev/${vg}/${lv}",
|
||||
fstype => $fstype,
|
||||
options => $mount_options.join(','),
|
||||
|
||||
@@ -12,18 +12,28 @@ class profiles::base::facts {
|
||||
mode => '0755',
|
||||
}
|
||||
|
||||
# facts to create
|
||||
# cleanup old facts files
|
||||
$fact_list = [ 'enc_role', 'enc_env' ]
|
||||
|
||||
# Manage the external fact file with content from the template
|
||||
$fact_list.each | String $item | {
|
||||
file { "${facts_d_path}/${item}.txt":
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
content => template("profiles/base/facts/${item}.erb"),
|
||||
require => File[$facts_d_path],
|
||||
ensure => absent,
|
||||
}
|
||||
}
|
||||
|
||||
# ensure the path to the custom store exists
|
||||
file { '/root/.cache':
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0750',
|
||||
}
|
||||
|
||||
# create the file that will be read
|
||||
file { '/root/.cache/custom_facts.yaml':
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
content => template('profiles/base/facts/custom_facts.yaml.erb'),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# profiles::base::groups
|
||||
# simple group management
|
||||
class profiles::base::groups (
|
||||
Hash $local = {},
|
||||
) {
|
||||
$local.each |$group, $data| {
|
||||
group { $group:
|
||||
name => $group,
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ class profiles::base::motd (
|
||||
String $nic = $facts['networking']['primary'],
|
||||
String $os_name = $facts['os']['name'],
|
||||
String $os_release = $facts['os']['release']['full'],
|
||||
String $location = "${facts['country']}-${facts['region']}",
|
||||
String $env = $facts['environment'],
|
||||
) {
|
||||
|
||||
# Use the regsubst function to remove the 'roles::' prefix from the role name
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# profiles::base::repos
|
||||
class profiles::base::repos {
|
||||
# manage package repositories
|
||||
case $facts['os']['family'] {
|
||||
'RedHat': {
|
||||
include profiles::yum::global
|
||||
include profiles::firewall::firewalld
|
||||
}
|
||||
'Debian': {
|
||||
include profiles::apt::global
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported OS family ${facts['os']['family']}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# manage the root user
|
||||
class profiles::base::root {
|
||||
|
||||
# TODO
|
||||
# for now, add some root directories
|
||||
|
||||
file {'/root/.config':
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0600',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
# profiles::cobbler::config
|
||||
class profiles::cobbler::config {
|
||||
|
||||
include profiles::cobbler::params
|
||||
|
||||
$default_password_crypted = $profiles::cobbler::params::default_password_crypted
|
||||
$httpd_ssl_certificate = $profiles::cobbler::params::httpd_ssl_certificate
|
||||
$httpd_ssl_privatekey = $profiles::cobbler::params::httpd_ssl_privatekey
|
||||
$pxe_just_once = $profiles::cobbler::params::pxe_just_once
|
||||
$is_cobbler_master = $profiles::cobbler::params::is_cobbler_master
|
||||
$service_cname = $profiles::cobbler::params::service_cname
|
||||
$next_server = $profiles::cobbler::params::next_server
|
||||
$server = $profiles::cobbler::params::server
|
||||
|
||||
# manage the cobbler settings file
|
||||
file { '/etc/cobbler/settings.yaml':
|
||||
ensure => 'file',
|
||||
content => template('profiles/cobbler/settings.yaml.erb'),
|
||||
group => 'apache',
|
||||
owner => 'root',
|
||||
mode => '0640',
|
||||
require => Package['cobbler'],
|
||||
notify => Service['cobblerd'],
|
||||
}
|
||||
|
||||
# manage the debmirror config to meet cobbler requirements
|
||||
file { '/etc/debmirror.conf':
|
||||
ensure => 'file',
|
||||
content => template('profiles/cobbler/debmirror.conf.erb'),
|
||||
group => 'root',
|
||||
owner => 'root',
|
||||
mode => '0644',
|
||||
require => Package['debmirror'],
|
||||
}
|
||||
|
||||
# manage the httpd ssl configuration
|
||||
file { '/etc/httpd/conf.d/ssl.conf':
|
||||
ensure => 'file',
|
||||
content => template('profiles/cobbler/httpd_ssl.conf.erb'),
|
||||
group => 'root',
|
||||
owner => 'root',
|
||||
mode => '0644',
|
||||
require => Package['httpd'],
|
||||
notify => Service['httpd'],
|
||||
}
|
||||
|
||||
# fix permissions in /var/lib/cobbler/web.ss
|
||||
file {'/var/lib/cobbler/web.ss':
|
||||
ensure => 'file',
|
||||
group => 'root',
|
||||
owner => 'apache',
|
||||
mode => '0660',
|
||||
require => Package['cobbler'],
|
||||
notify => Service['cobblerd'],
|
||||
}
|
||||
|
||||
# manage the main ipxe menu script
|
||||
file { '/var/lib/tftpboot/main.ipxe':
|
||||
ensure => 'file',
|
||||
content => template('profiles/cobbler/main.ipxe.erb'),
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
require => Package['cobbler'],
|
||||
}
|
||||
|
||||
# export cnames for cobbler
|
||||
if $is_cobbler_master {
|
||||
profiles::dns::record { "${::facts['networking']['fqdn']}_${service_cname}_CNAME":
|
||||
value => $::facts['networking']['hostname'],
|
||||
type => 'CNAME',
|
||||
record => "${service_cname}.",
|
||||
zone => $::facts['networking']['domain'],
|
||||
order => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# profiles::cobbler::init
|
||||
class profiles::cobbler::init (
|
||||
) {
|
||||
# wait for enc_role to be populated, needed for hieradata to match
|
||||
if $facts['enc_role'] == 'roles::infra::cobbler::server' {
|
||||
include profiles::cobbler::config
|
||||
include profiles::cobbler::install
|
||||
include profiles::cobbler::ipxebins
|
||||
include profiles::cobbler::selinux
|
||||
include profiles::cobbler::service
|
||||
|
||||
Class['profiles::cobbler::install']
|
||||
-> Class['profiles::cobbler::config']
|
||||
-> Class['profiles::cobbler::ipxebins']
|
||||
-> Class['profiles::cobbler::selinux']
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# profiles::cobbler::install
|
||||
class profiles::cobbler::install {
|
||||
|
||||
include profiles::cobbler::params
|
||||
|
||||
$packages = $profiles::cobbler::params::packages
|
||||
|
||||
ensure_packages($packages, { ensure => 'present' })
|
||||
|
||||
# move the /var/www/cobbler directory to /data/cobbler
|
||||
if ! $facts['cobbler_var_www_islink'] and ! $facts['cobbler_data_exists'] {
|
||||
exec {'move_cobbler_data':
|
||||
command => 'mv /var/www/cobbler /data/cobbler',
|
||||
onlyif => 'test -d /var/www/cobbler',
|
||||
path => ['/bin', '/usr/bin'],
|
||||
before => Service['cobblerd'],
|
||||
}
|
||||
file { '/var/www/cobbler':
|
||||
ensure => 'link',
|
||||
target => '/data/cobbler',
|
||||
require => Exec['move_cobbler_data'],
|
||||
before => Service['httpd'],
|
||||
notify => Service['httpd'],
|
||||
}
|
||||
}
|
||||
if ! $facts['cobbler_var_www_exists'] and $facts['cobbler_data_exists'] {
|
||||
file { '/var/www/cobbler':
|
||||
ensure => 'link',
|
||||
target => '/data/cobbler',
|
||||
before => Service['httpd'],
|
||||
notify => Service['httpd'],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
# profiles::cobbler::ipxebins
|
||||
class profiles::cobbler::ipxebins {
|
||||
|
||||
include profiles::cobbler::params
|
||||
|
||||
# download the custom undionly.kpxe file
|
||||
# https://gist.github.com/rikka0w0/50895b82cbec8a3a1e8c7707479824c1
|
||||
exec { 'download_undionly_kpxe':
|
||||
command => 'wget -O /var/lib/tftpboot/undionly.kpxe http://repos.main.unkin.net/unkin/8/x86_64/os/Archives/undionly.kpxe',
|
||||
path => ['/bin', '/usr/bin'],
|
||||
creates => '/var/lib/tftpboot/undionly.kpxe',
|
||||
}
|
||||
|
||||
# set correct permissions ipxe boot image to tftpboot
|
||||
file { '/var/lib/tftpboot/undionly.kpxe':
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
require => [
|
||||
Package['ipxe-bootimgs'],
|
||||
Package['cobbler'],
|
||||
Exec['download_undionly_kpxe']
|
||||
],
|
||||
}
|
||||
|
||||
# download the custom ipxe.efi file
|
||||
# https://gist.github.com/rikka0w0/50895b82cbec8a3a1e8c7707479824c1
|
||||
exec { 'download_ipxe_efi':
|
||||
command => 'wget -O /var/lib/tftpboot/ipxe.efi http://repos.main.unkin.net/unkin/8/x86_64/os/Archives/ipxe.efi',
|
||||
path => ['/bin', '/usr/bin'],
|
||||
creates => '/var/lib/tftpboot/ipxe.efi',
|
||||
}
|
||||
|
||||
# set correct permissions ipxe boot image to tftpboot
|
||||
file { '/var/lib/tftpboot/ipxe.efi':
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
require => [
|
||||
Package['ipxe-bootimgs'],
|
||||
Package['cobbler'],
|
||||
Exec['download_ipxe_efi']
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# profiles::cobbler::params
|
||||
class profiles::cobbler::params (
|
||||
Stdlib::Absolutepath $httpd_ssl_certificate = '/etc/pki/tls/vault/certificate.crt',
|
||||
Stdlib::Absolutepath $httpd_ssl_privatekey = '/etc/pki/tls/vault/private.key',
|
||||
Stdlib::Absolutepath $tftpboot_path = '/var/lib/tftpboot/boot',
|
||||
Stdlib::Fqdn $service_cname = $facts['networking']['fqdn'],
|
||||
String $default_password_crypted = 'changeme',
|
||||
String $server = $::facts['networking']['ip'],
|
||||
String $next_server = $::facts['networking']['ip'],
|
||||
Boolean $pxe_just_once = true,
|
||||
Boolean $is_cobbler_master = false,
|
||||
Array $packages = [
|
||||
'cobbler',
|
||||
'cobbler3.2-web',
|
||||
'httpd',
|
||||
'syslinux',
|
||||
'dnf-plugins-core',
|
||||
'debmirror',
|
||||
'pykickstart',
|
||||
'fence-agents',
|
||||
'selinux-policy-devel',
|
||||
'ipxe-bootimgs',
|
||||
]
|
||||
){
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
# profiles::cobbler::selinux
|
||||
class profiles::cobbler::selinux inherits profiles::cobbler::params {
|
||||
|
||||
include profiles::cobbler::params
|
||||
|
||||
$tftpboot_path = $profiles::cobbler::params::tftpboot_path
|
||||
|
||||
# manage selinux requirements for cobbler
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
$enable_sebooleans = [
|
||||
'httpd_can_network_connect_cobbler',
|
||||
'httpd_serve_cobbler_files',
|
||||
'cobbler_can_network_connect'
|
||||
]
|
||||
|
||||
$enable_sebooleans.each |$bool| {
|
||||
selboolean { $bool:
|
||||
value => on,
|
||||
persistent => true,
|
||||
}
|
||||
}
|
||||
|
||||
selinux::fcontext { $tftpboot_path:
|
||||
ensure => 'present',
|
||||
seltype => 'cobbler_var_lib_t',
|
||||
pathspec => "${tftpboot_path}(/.*)?",
|
||||
}
|
||||
selinux::fcontext { '/data/cobbler':
|
||||
ensure => 'present',
|
||||
seltype => 'cobbler_var_lib_t',
|
||||
pathspec => '/data/cobbler(/.*)?',
|
||||
}
|
||||
|
||||
exec { "restorecon_${tftpboot_path}":
|
||||
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
|
||||
command => "restorecon -Rv ${tftpboot_path}",
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext[$tftpboot_path],
|
||||
}
|
||||
exec { 'restorecon_/data/cobbler':
|
||||
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
|
||||
command => 'restorecon -Rv /data/cobbler',
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext['/data/cobbler'],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# profiles::cobbler::service
|
||||
class profiles::cobbler::service inherits profiles::cobbler::params {
|
||||
|
||||
# ensure cobblerd is running
|
||||
service {'cobblerd':
|
||||
ensure => 'running',
|
||||
enable => true,
|
||||
require => File['/etc/cobbler/settings.yaml'],
|
||||
}
|
||||
|
||||
# ensure httpd is running
|
||||
service {'httpd':
|
||||
ensure => 'running',
|
||||
enable => true,
|
||||
require => File['/etc/httpd/conf.d/ssl.conf'],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
# profiles::consul::client
|
||||
class profiles::consul::client (
|
||||
String $secret_id_salt = '',
|
||||
Stdlib::Fqdn $consul_hostname = 'consul.service.consul',
|
||||
Enum['http','https'] $consul_protocol = 'http',
|
||||
Stdlib::Port $consul_port = 8500,
|
||||
String $consul_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'),
|
||||
Boolean $members_lookup = false,
|
||||
String $members_role = undef,
|
||||
Array $consul_servers = [],
|
||||
Stdlib::Absolutepath $data_dir = '/opt/consul',
|
||||
Array[Hash] $node_rules = [],
|
||||
) {
|
||||
|
||||
if $facts['enc_role'] != $members_role {
|
||||
|
||||
# set a datacentre/cluster name
|
||||
$consul_cluster = "${::facts['country']}-${::facts['region']}"
|
||||
|
||||
# if lookup is enabled, find all the hosts in the specified role and create the servers_array
|
||||
if $members_lookup {
|
||||
|
||||
# check that the role is also set
|
||||
unless !($members_role == undef) {
|
||||
fail("members_role must be provided for ${title} when members_lookup is True")
|
||||
}
|
||||
|
||||
# if it is, find hosts, sort them so they dont cause changes every run
|
||||
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn'))
|
||||
|
||||
# else use provided array from params
|
||||
}else{
|
||||
$servers_array = $consul_servers
|
||||
}
|
||||
|
||||
# deploy the consul agent
|
||||
class { 'consul':
|
||||
config_hash => {
|
||||
'data_dir' => $data_dir,
|
||||
'datacenter' => $consul_cluster,
|
||||
'log_level' => 'INFO',
|
||||
'node_name' => $facts['networking']['fqdn'],
|
||||
'retry_join' => $servers_array,
|
||||
'bind_addr' => $::facts['networking']['ip'],
|
||||
'advertise_addr' => $::facts['networking']['ip'],
|
||||
'acl' => {
|
||||
tokens => {
|
||||
default => fqdn_uuid("${facts['networking']['fqdn']}-${secret_id_salt}")
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
# Create ACL policy that allows nodes to update themselves and read others
|
||||
consul_policy { $facts['networking']['hostname']:
|
||||
description => "${facts['networking']['fqdn']} puppet-generated-policy",
|
||||
rules => $node_rules,
|
||||
acl_api_token => $consul_api_token,
|
||||
hostname => $consul_hostname,
|
||||
protocol => $consul_protocol,
|
||||
port => $consul_port,
|
||||
}
|
||||
|
||||
consul_token { $facts['networking']['hostname']:
|
||||
accessor_id => fqdn_uuid($facts['networking']['fqdn']),
|
||||
description => "${facts['networking']['fqdn']} puppet-generated-token",
|
||||
policies_by_name => [$facts['networking']['hostname']],
|
||||
acl_api_token => $consul_api_token,
|
||||
secret_id => fqdn_uuid("${facts['networking']['fqdn']}-${secret_id_salt}"),
|
||||
hostname => $consul_hostname,
|
||||
protocol => $consul_protocol,
|
||||
port => $consul_port,
|
||||
|
||||
}
|
||||
|
||||
# ensure the consul token is saved for the root user
|
||||
file {'/root/.config/consul_node_token':
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0600',
|
||||
content => Sensitive(fqdn_uuid("${facts['networking']['fqdn']}-${secret_id_salt}")),
|
||||
require => File['/root/.config'],
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# profiles::consul::policies
|
||||
class profiles::consul::policies (
|
||||
String $root_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'),
|
||||
) {
|
||||
|
||||
consul_policy { 'node_editor':
|
||||
description => 'Policy to read/write all nodes puppet-generated-policy',
|
||||
rules => [
|
||||
{
|
||||
'resource' => 'node',
|
||||
'segment' => '',
|
||||
'disposition' => 'write'
|
||||
},
|
||||
{
|
||||
'resource' => 'node',
|
||||
'segment' => '',
|
||||
'disposition' => 'read'
|
||||
}
|
||||
],
|
||||
acl_api_token => $root_api_token,
|
||||
hostname => $facts['networking']['ip'],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# profile::consul::prepared_query
|
||||
class profiles::consul::prepared_query (
|
||||
String $root_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'),
|
||||
Hash $rules = {},
|
||||
) {
|
||||
|
||||
$rules.each | $rule, $data | {
|
||||
consul_prepared_query { $rule:
|
||||
acl_api_token => $root_api_token,
|
||||
hostname => $facts['networking']['ip'],
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
# profiles::consul::server
|
||||
class profiles::consul::server (
|
||||
Variant[
|
||||
Undef,
|
||||
String
|
||||
] $gossip_key = undef,
|
||||
Variant[
|
||||
Undef,
|
||||
String
|
||||
] $primary_datacenter = undef,
|
||||
Hash $acl = {},
|
||||
Hash $ports = {},
|
||||
Hash $addresses = {},
|
||||
Boolean $members_lookup = false,
|
||||
String $members_role = undef,
|
||||
Array $consul_servers = [],
|
||||
Boolean $enable_ui = true,
|
||||
Boolean $enable_ui_config = true,
|
||||
Boolean $manage_repo = false,
|
||||
String $package_ensure = 'latest',
|
||||
String $package_name = 'consul',
|
||||
Integer $bootstrap_count = 1,
|
||||
String $domain = 'consul',
|
||||
Integer $raft_multiplier = 1,
|
||||
Enum[
|
||||
'allow',
|
||||
'deny',
|
||||
'extend-cache',
|
||||
'async-cache'
|
||||
] $acl_down_policy = 'extend-cache',
|
||||
Enum[
|
||||
'allow',
|
||||
'deny'
|
||||
] $acl_default_policy = 'deny',
|
||||
Enum[
|
||||
'url',
|
||||
'package',
|
||||
'docker',
|
||||
'none'
|
||||
] $install_method = 'package',
|
||||
Stdlib::IP::Address $client_addr = '0.0.0.0',
|
||||
Stdlib::Absolutepath $data_dir = '/opt/consul',
|
||||
Stdlib::Absolutepath $bin_dir = '/usr/bin',
|
||||
Boolean $disable_remote_exec = true,
|
||||
Boolean $disable_update_check = true,
|
||||
Boolean $join_remote_regions = false,
|
||||
Array[String] $remote_regions = [],
|
||||
) {
|
||||
|
||||
# wait for all attributes to be ready
|
||||
if $facts['enc_role'] == $members_role {
|
||||
|
||||
# set a datacentre/cluster name
|
||||
$consul_cluster = "${::facts['country']}-${::facts['region']}"
|
||||
|
||||
# if lookup is enabled, find all the hosts in the specified role and create the servers_array
|
||||
if $members_lookup {
|
||||
|
||||
# check that the role is also set
|
||||
unless !($members_role == undef) {
|
||||
fail("members_role must be provided for ${title} when members_lookup is True")
|
||||
}
|
||||
|
||||
# if it is, find hosts, sort them so they dont cause changes every run
|
||||
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn'))
|
||||
|
||||
if $join_remote_regions {
|
||||
# get all nodes in the members_role for each other region
|
||||
$region_to_servers = $remote_regions.reduce({}) |$memo, $region| {
|
||||
$servers = sort(query_nodes("enc_role='${members_role}' and region='${region}'", 'networking.fqdn'))
|
||||
$memo + { $region => $servers }
|
||||
}
|
||||
|
||||
# sort and flatten the regions into a single array of fqdns
|
||||
$remote_servers_array = sort(flatten($region_to_servers.values))
|
||||
|
||||
} else {
|
||||
# else just send an empty array
|
||||
$remote_servers_array = []
|
||||
}
|
||||
|
||||
# else use provided array from params
|
||||
}else{
|
||||
$servers_array = $consul_servers
|
||||
}
|
||||
|
||||
# if $data_dir starts with /data, ensure the data mount exists
|
||||
if ($data_dir.stdlib::start_with('/data') and $::facts['mountpoints']['/data']) or ! $data_dir.stdlib::start_with('/data') {
|
||||
|
||||
# install consul
|
||||
class { 'consul':
|
||||
install_method => $install_method,
|
||||
manage_repo => $manage_repo,
|
||||
package_name => $package_name,
|
||||
package_ensure => $package_ensure,
|
||||
bin_dir => $bin_dir,
|
||||
config_hash => {
|
||||
'primary_datacenter' => $primary_datacenter,
|
||||
'acl' => $acl,
|
||||
'ports' => $ports,
|
||||
'addresses' => $addresses,
|
||||
'disable_remote_exec' => $disable_remote_exec,
|
||||
'disable_update_check' => $disable_update_check,
|
||||
'domain' => $domain,
|
||||
'bootstrap_expect' => $bootstrap_count,
|
||||
'client_addr' => '0.0.0.0',
|
||||
'data_dir' => $data_dir,
|
||||
'datacenter' => $consul_cluster,
|
||||
'log_level' => 'INFO',
|
||||
'node_name' => $::facts['networking']['fqdn'],
|
||||
'server' => true,
|
||||
'ui' => $enable_ui,
|
||||
'ui_config' => { 'enabled' => $enable_ui_config },
|
||||
'performance' => { 'raft_multiplier' => $raft_multiplier },
|
||||
'bind_addr' => $::facts['networking']['ip'],
|
||||
'advertise_addr' => $::facts['networking']['ip'],
|
||||
'retry_join' => $servers_array,
|
||||
'retry_join_wan' => $remote_servers_array,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
# consul before extra services
|
||||
if defined(Class['consul']) {
|
||||
|
||||
# include nginx, policies and tokens
|
||||
include profiles::nginx::simpleproxy
|
||||
include profiles::consul::policies
|
||||
include profiles::consul::tokens
|
||||
include profiles::consul::prepared_query
|
||||
|
||||
# get the dns port from the $ports hash, otherwise use the default
|
||||
$dns_port = pick($ports['dns'], 8600)
|
||||
|
||||
# install dnsmasq
|
||||
package { 'dnsmasq':
|
||||
ensure => installed,
|
||||
}
|
||||
|
||||
# create the 10-consul.conf file
|
||||
file { '/etc/dnsmasq.d/10-consul.conf':
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
content => "server=/${domain}/${::facts['networking']['ip']}#${dns_port}\n",
|
||||
require => Package['dnsmasq'],
|
||||
notify => Service['dnsmasq'],
|
||||
}
|
||||
|
||||
# ensure dnsmasq service is running and enabled at boot
|
||||
service { 'dnsmasq':
|
||||
ensure => running,
|
||||
enable => true,
|
||||
subscribe => File['/etc/dnsmasq.d/10-consul.conf'], # Restart dnsmasq if the consul config changes
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# profiles::consul::tokens
|
||||
class profiles::consul::tokens (
|
||||
String $root_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'),
|
||||
){
|
||||
|
||||
consul_token { 'node_editor':
|
||||
accessor_id => lookup('profiles::consul::token::node_editor::accessor_id'),
|
||||
policies_by_name => ['node_editor'],
|
||||
acl_api_token => $root_api_token,
|
||||
secret_id => lookup('profiles::consul::token::node_editor::secret_id'),
|
||||
hostname => $facts['networking']['ip'],
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,9 @@ class profiles::defaults {
|
||||
}
|
||||
|
||||
Package {
|
||||
ensure => present,
|
||||
ensure => present,
|
||||
require => Class['profiles::base::repos']
|
||||
|
||||
}
|
||||
|
||||
File {
|
||||
@@ -27,4 +29,13 @@ class profiles::defaults {
|
||||
ensure => present,
|
||||
shell => '/bin/bash',
|
||||
}
|
||||
|
||||
Yumrepo {
|
||||
ensure => 'present',
|
||||
enabled => 1,
|
||||
gpgcheck => 1,
|
||||
mirrorlist => 'absent',
|
||||
require => Class['profiles::pki::vaultca'],
|
||||
notify => Exec['dnf_makecache'],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# profiles::dhcp::server
|
||||
class profiles::dhcp::server (
|
||||
Array[Stdlib::Host] $ntpservers = [
|
||||
'0.au.pool.ntp.org',
|
||||
'1.au.pool.ntp.org',
|
||||
'2.au.pool.ntp.org',
|
||||
'3.au.pool.ntp.org'
|
||||
],
|
||||
Array[String] $interfaces = ['eth0'],
|
||||
Integer $default_lease_time = 86400,
|
||||
Array[String] $globaloptions = [],
|
||||
Hash $pools = {},
|
||||
Hash $classes = {},
|
||||
){
|
||||
|
||||
if $facts['enc_role'] == 'roles::infra::dhcp::server' {
|
||||
class { 'dhcp':
|
||||
service_ensure => running,
|
||||
interfaces => $interfaces,
|
||||
ntpservers => $ntpservers,
|
||||
default_lease_time => $default_lease_time,
|
||||
globaloptions => $globaloptions
|
||||
}
|
||||
|
||||
# if pools, import them
|
||||
$pools.each | $name, $data | {
|
||||
dhcp::pool { $name:
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
|
||||
# if classes, import them
|
||||
$classes.each | $name, $data | {
|
||||
dhcp::dhcp_class { $name:
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,24 @@ class profiles::dns::base (
|
||||
String $ns_role = undef,
|
||||
Array $search = [],
|
||||
Array $nameservers = ['8.8.8.8', '1.1.1.1'],
|
||||
Enum[
|
||||
'all',
|
||||
'region',
|
||||
'country'
|
||||
] $use_ns = 'all',
|
||||
){
|
||||
|
||||
# install bind_utils
|
||||
include bind::updater
|
||||
|
||||
# if ns_role is set, find all hosts matching that enc_role
|
||||
if $ns_role == undef {
|
||||
$nameserver_array = $nameservers
|
||||
}else{
|
||||
$nameserver_array = query_nodes("enc_role='${ns_role}'", 'networking.ip')
|
||||
$nameserver_array = $ns_role ? {
|
||||
undef => $nameservers,
|
||||
default => $use_ns ? {
|
||||
'all' => query_nodes("enc_role='${ns_role}'", 'networking.ip'),
|
||||
'region' => query_nodes("enc_role='${ns_role}' and region=${facts['region']}", 'networking.ip'),
|
||||
'country' => query_nodes("enc_role='${ns_role}' and country=${facts['country']}", 'networking.ip'),
|
||||
}
|
||||
}
|
||||
|
||||
# if search is undef, fallback to domainname from facts
|
||||
@@ -21,8 +32,8 @@ class profiles::dns::base (
|
||||
|
||||
# include resolvconf class
|
||||
class { 'profiles::dns::resolvconf':
|
||||
nameservers => $nameserver_array,
|
||||
search_domains => $search_array,
|
||||
nameservers => sort($nameserver_array),
|
||||
search_domains => sort($search_array),
|
||||
}
|
||||
|
||||
# export dns records for client
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# profiles::dns::master authoritative service
|
||||
class profiles::dns::master (
|
||||
Array[String] $nameservers,
|
||||
Stdlib::AbsolutePath $basedir,
|
||||
Hash $acls = {},
|
||||
Hash $zones = {},
|
||||
@@ -13,8 +12,27 @@ class profiles::dns::master (
|
||||
String $owner = 'root',
|
||||
String $group = 'named',
|
||||
Boolean $dnssec = false,
|
||||
Variant[String, Undef] $ns_role = undef,
|
||||
Enum['all', 'region', 'country'] $use_ns = 'all',
|
||||
){
|
||||
|
||||
# if ns_role is set, find all hosts matching that enc_role, otherwise use the current host
|
||||
$nameservers_array = $ns_role ? {
|
||||
undef => [$facts['networking']['fqdn']],
|
||||
default => $use_ns ? {
|
||||
'all' => query_nodes("enc_role='${ns_role}'", 'networking.fqdn'),
|
||||
'region' => query_nodes("enc_role='${ns_role}' and region=${facts['region']}", 'networking.fqdn'),
|
||||
'country' => query_nodes("enc_role='${ns_role}' and country=${facts['country']}", 'networking.fqdn'),
|
||||
}
|
||||
}
|
||||
|
||||
# if nameservers is empty, use the current host, otherwise use nameservers_array as nameservers
|
||||
$nameservers = empty($nameservers_array) ? {
|
||||
true => [$facts['networking']['fqdn']],
|
||||
false => $nameservers_array,
|
||||
default => [$facts['networking']['fqdn']],
|
||||
}
|
||||
|
||||
class {'profiles::dns::server':
|
||||
acls => $acls,
|
||||
zones => $zones,
|
||||
@@ -37,7 +55,7 @@ class profiles::dns::master (
|
||||
profiles::dns::zone { $name:
|
||||
zone => $data['domain'],
|
||||
basedir => $basedir,
|
||||
nameservers => $nameservers,
|
||||
nameservers => sort($nameservers),
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
before => Bind::Zone[$name]
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# profiles::edgecache::init
|
||||
class profiles::edgecache::init {
|
||||
|
||||
if $facts['enc_role'] == 'roles::infra::storage::edgecache' {
|
||||
|
||||
include profiles::edgecache::nginx
|
||||
include profiles::edgecache::selinux
|
||||
|
||||
Class['profiles::edgecache::nginx']
|
||||
-> Class['profiles::edgecache::selinux']
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
# profiles::edgecache::nginx
|
||||
class profiles::edgecache::nginx {
|
||||
|
||||
include profiles::edgecache::params
|
||||
|
||||
$data_root = $profiles::edgecache::params::data_root
|
||||
$nginx_vhost = $profiles::edgecache::params::nginx_vhost
|
||||
$nginx_aliases = $profiles::edgecache::params::nginx_aliases
|
||||
$nginx_port = $profiles::edgecache::params::nginx_port
|
||||
$nginx_ssl_port = $profiles::edgecache::params::nginx_ssl_port
|
||||
$nginx_listen_mode = $profiles::edgecache::params::nginx_listen_mode
|
||||
$nginx_cert_type = $profiles::edgecache::params::nginx_cert_type
|
||||
$nginx_resolvers_enable = $profiles::edgecache::params::nginx_resolvers_enable
|
||||
$nginx_resolvers_ipv4only = $profiles::edgecache::params::nginx_resolvers_ipv4only
|
||||
|
||||
# select the certificates to use based on cert type
|
||||
case $nginx_cert_type {
|
||||
'puppet': {
|
||||
$selected_ssl_cert = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt"
|
||||
$selected_ssl_key = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key"
|
||||
}
|
||||
'vault': {
|
||||
$selected_ssl_cert = '/etc/pki/tls/vault/certificate.crt'
|
||||
$selected_ssl_key = '/etc/pki/tls/vault/private.key'
|
||||
}
|
||||
default: {
|
||||
# enum param prevents this ever being reached
|
||||
}
|
||||
}
|
||||
|
||||
# set variables based on the listen_mode
|
||||
case $nginx_listen_mode {
|
||||
'http': {
|
||||
$enable_ssl = false
|
||||
$ssl_cert = undef
|
||||
$ssl_key = undef
|
||||
$listen_port = $nginx_port
|
||||
$listen_ssl_port = undef
|
||||
$extras_hash = {}
|
||||
}
|
||||
'https': {
|
||||
$enable_ssl = true
|
||||
$ssl_cert = $selected_ssl_cert
|
||||
$ssl_key = $selected_ssl_key
|
||||
$listen_port = $nginx_ssl_port
|
||||
$listen_ssl_port = $nginx_ssl_port
|
||||
$extras_hash = {
|
||||
'subscribe' => [File[$ssl_cert], File[$ssl_key]],
|
||||
}
|
||||
}
|
||||
'both': {
|
||||
$enable_ssl = true
|
||||
$ssl_cert = $selected_ssl_cert
|
||||
$ssl_key = $selected_ssl_key
|
||||
$listen_port = $nginx_port
|
||||
$listen_ssl_port = $nginx_ssl_port
|
||||
$extras_hash = {
|
||||
'subscribe' => [File[$ssl_cert], File[$ssl_key]],
|
||||
}
|
||||
}
|
||||
default: {
|
||||
# enum param prevents this ever being reached
|
||||
}
|
||||
}
|
||||
|
||||
if $nginx_resolvers_ipv4only and $nginx_resolvers_enable {
|
||||
$resolvers = $facts['nameservers'].join(' ')
|
||||
file { '/etc/nginx/conf.d/resolvers.conf':
|
||||
ensure => file,
|
||||
content => "resolver ${resolvers} ipv4=on;\n",
|
||||
}
|
||||
}
|
||||
|
||||
# set the server_names
|
||||
$server_names = unique([$facts['networking']['fqdn'], $nginx_vhost] + $nginx_aliases)
|
||||
|
||||
# define the default parameters for the nginx server
|
||||
$defaults = {
|
||||
'listen_port' => $listen_port,
|
||||
'server_name' => $server_names,
|
||||
'use_default_location' => true,
|
||||
'access_log' => "/var/log/nginx/${nginx_vhost}_access.log",
|
||||
'error_log' => "/var/log/nginx/${nginx_vhost}_error.log",
|
||||
'www_root' => "${data_root}/pub",
|
||||
'autoindex' => 'on',
|
||||
'ssl' => $enable_ssl,
|
||||
'ssl_cert' => $ssl_cert,
|
||||
'ssl_key' => $ssl_key,
|
||||
'ssl_port' => $listen_ssl_port,
|
||||
}
|
||||
|
||||
# ensure the requires directories exist
|
||||
$profiles::edgecache::params::directories.each |$name,$data| {
|
||||
file { $name:
|
||||
ensure => 'directory',
|
||||
before => Class['nginx'],
|
||||
mode => '0775',
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
|
||||
# merge the hashes conditionally
|
||||
$nginx_parameters = merge($defaults, $extras_hash)
|
||||
|
||||
# manage the nginx class
|
||||
class { 'nginx':
|
||||
proxy_cache_path => {
|
||||
"${data_root}/cache" => 'cache:128m',
|
||||
},
|
||||
proxy_cache_levels => '1:2',
|
||||
proxy_cache_keys_zone => 'cache:128m',
|
||||
proxy_cache_max_size => '30000m',
|
||||
proxy_cache_inactive => '60d',
|
||||
proxy_temp_path => "${data_root}/cache_tmp",
|
||||
}
|
||||
|
||||
# create the nginx vhost with the merged parameters
|
||||
create_resources('nginx::resource::server', { $nginx_vhost => $nginx_parameters })
|
||||
|
||||
# create location mirrors
|
||||
$profiles::edgecache::params::mirrors.each |$name, $data| {
|
||||
nginx::resource::location { "${nginx_vhost}_${name}":
|
||||
server => $nginx_vhost,
|
||||
ssl => true,
|
||||
ssl_only => false,
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# profiles::edgecache::params
|
||||
class profiles::edgecache::params (
|
||||
Stdlib::Absolutepath $data_root = '/data/edgecache',
|
||||
Stdlib::Fqdn $nginx_vhost = $facts['networking']['fqdn'],
|
||||
Array[Stdlib::Host] $nginx_aliases = [],
|
||||
Stdlib::Port $nginx_port = 80,
|
||||
Stdlib::Port $nginx_ssl_port = 443,
|
||||
Enum['http','https','both'] $nginx_listen_mode = 'http',
|
||||
Enum['puppet', 'vault'] $nginx_cert_type = 'vault',
|
||||
Boolean $nginx_resolvers_enable = false,
|
||||
Boolean $nginx_resolvers_ipv4only = false,
|
||||
Hash $directories = {},
|
||||
Hash $mirrors = {},
|
||||
){
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
# profiles::edgecache::selinux
|
||||
class profiles::edgecache::selinux {
|
||||
|
||||
include profiles::edgecache::params
|
||||
|
||||
$data_root = $profiles::edgecache::params::data_root
|
||||
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
# set httpd_sys_content_t to all files under the www_root
|
||||
selinux::fcontext { "${data_root}/pub":
|
||||
ensure => 'present',
|
||||
seltype => 'httpd_sys_content_t',
|
||||
pathspec => "${data_root}/pub(/.*)?",
|
||||
}
|
||||
|
||||
# set httpd_sys_rw_content_t to all files under the cache_root
|
||||
selinux::fcontext { "${data_root}/cache":
|
||||
ensure => 'present',
|
||||
seltype => 'httpd_sys_rw_content_t',
|
||||
pathspec => "${data_root}/cache(/.*)?",
|
||||
}
|
||||
selinux::fcontext { "${data_root}/cache_tmp":
|
||||
ensure => 'present',
|
||||
seltype => 'httpd_sys_rw_content_t',
|
||||
pathspec => "${data_root}/cache_tmp(/.*)?",
|
||||
}
|
||||
|
||||
# make sure we can connect to other hosts
|
||||
selboolean { 'httpd_can_network_connect':
|
||||
persistent => true,
|
||||
value => 'on',
|
||||
}
|
||||
|
||||
exec { "restorecon_${data_root}/pub":
|
||||
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
|
||||
command => "restorecon -Rv ${data_root}/pub",
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext["${data_root}/pub"],
|
||||
}
|
||||
|
||||
exec { "restorecon_${data_root}/cache":
|
||||
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
|
||||
command => "restorecon -Rv ${data_root}/cache",
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext["${data_root}/cache"],
|
||||
}
|
||||
|
||||
exec { "restorecon_${data_root}/cache_tmp":
|
||||
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
|
||||
command => "restorecon -Rv ${data_root}/cache_tmp",
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext["${data_root}/cache_tmp"],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# profiles::firstrun::complete
|
||||
class profiles::firstrun::complete {
|
||||
|
||||
file { '/root/.cache':
|
||||
ensure => 'directory',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0750',
|
||||
}
|
||||
|
||||
file {'/root/.cache/puppet_firstrun_complete':
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0750',
|
||||
content => 'firstrun completed',
|
||||
require => File['/root/.cache'],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# profiles::firstrun::init
|
||||
class profiles::firstrun::init {
|
||||
|
||||
# include the required CA certificates
|
||||
include profiles::pki::vaultca
|
||||
|
||||
# fast install packages on the first run
|
||||
include profiles::base::repos
|
||||
include profiles::firstrun::packages
|
||||
|
||||
# mark the firstrun as done
|
||||
include profiles::firstrun::complete
|
||||
|
||||
|
||||
Class['profiles::defaults']
|
||||
-> Class['profiles::pki::vaultca']
|
||||
-> Class['profiles::base::repos']
|
||||
-> Class['profiles::firstrun::packages']
|
||||
-> Class['profiles::firstrun::complete']
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# profiles::firstrun::packages
|
||||
class profiles::firstrun::packages {
|
||||
# include the correct package repositories, define the install_packages exec
|
||||
case $facts['os']['family'] {
|
||||
'RedHat': {
|
||||
include profiles::yum::global
|
||||
$install_command = 'dnf install -y'
|
||||
}
|
||||
'Debian': {
|
||||
include profiles::apt::global
|
||||
$install_command = 'apt-get install -y'
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported OS family ${facts['os']['family']}")
|
||||
}
|
||||
}
|
||||
|
||||
# get all the packages to install, and convert into a space separated list
|
||||
$packages = hiera_array('profiles::packages::install', [])
|
||||
$package_list = $packages.join(' ')
|
||||
|
||||
# install all the packages
|
||||
exec { 'install_packages':
|
||||
command => "${install_command} ${package_list}",
|
||||
path => ['/bin', '/usr/bin'],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
# profiles::gitea::init
|
||||
class profiles::gitea::init (
|
||||
String $mysql_pass = '',
|
||||
String $lfs_jwt_secret = '',
|
||||
) {
|
||||
|
||||
include profiles::nginx::simpleproxy
|
||||
|
||||
class { 'gitea':
|
||||
ensure => '1.22.0',
|
||||
checksum => 'a31086f073cb9592d28611394b2de3655db515d961e4fdcf5b549cb40753ef3d',
|
||||
custom_configuration => {
|
||||
'' => {
|
||||
'APP_NAME' => 'Gitea',
|
||||
'RUN_USER' => 'git',
|
||||
'RUN_MODE' => 'prod',
|
||||
},
|
||||
'repository' => {
|
||||
'ROOT' => '/data/gitea/repos',
|
||||
'FORCE_PRIVATE' => false,
|
||||
'MAX_CREATION_LIMIT' => -1,
|
||||
'DISABLE_HTTP_GIT' => false,
|
||||
'DEFAULT_BRANCH' => 'main',
|
||||
'DEFAULT_PRIVATE' => 'last',
|
||||
},
|
||||
'ui' => {
|
||||
'SHOW_USER_EMAIL' => false,
|
||||
},
|
||||
'server' => {
|
||||
'PROTOCOL' => 'http',
|
||||
'DOMAIN' => 'git.query.consul',
|
||||
'ROOT_URL' => 'https://git.query.consul',
|
||||
'HTTP_ADDR' => '0.0.0.0',
|
||||
'HTTP_PORT' => 3000,
|
||||
'START_SSH_SERVER' => false,
|
||||
'SSH_DOMAIN' => 'git.query.consul',
|
||||
'SSH_PORT' => 2222,
|
||||
'SSH_LISTEN_HOST' => '0.0.0.0',
|
||||
'OFFLINE_MODE' => true,
|
||||
'APP_DATA_PATH' => '/var/lib/gitea/data',
|
||||
'SSH_LISTEN_PORT' => 22,
|
||||
},
|
||||
'database' => {
|
||||
'DB_TYPE' => 'mysql',
|
||||
'HOST' => 'mariadb-prod.service.au-syd1.consul:3306',
|
||||
'NAME' => 'gitea',
|
||||
'USER' => 'gitea',
|
||||
'PASSWD' => Sensitive($mysql_pass),
|
||||
'SSL_MODE' => 'disable',
|
||||
'PATH' => '/var/lib/gitea/data/gitea.db',
|
||||
'LOG_SQL' => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# profiles::haproxy::backends
|
||||
class profiles::haproxy::backends {
|
||||
# set location_environment
|
||||
$location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}"
|
||||
|
||||
# for each backend:
|
||||
$backends = lookup('profiles::haproxy::backends', Hash, 'deep', {})
|
||||
$backends.each |$backend, $data| {
|
||||
|
||||
# create backend
|
||||
haproxy::backend { $backend:
|
||||
* => $data,
|
||||
}
|
||||
|
||||
# collect exported resources
|
||||
$tag = "${backend}_${location_environment}"
|
||||
Haproxy::Balancermember <<| tag == $tag |>>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# profiles::haproxy::balancemember
|
||||
define profiles::haproxy::balancemember (
|
||||
String $service,
|
||||
Array[Stdlib::Port] $ports,
|
||||
Array $options = ['check'],
|
||||
) {
|
||||
|
||||
$location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}"
|
||||
$balancemember_tag = "${service}_${location_environment}"
|
||||
|
||||
@@haproxy::balancermember { $title:
|
||||
listening_service => $service,
|
||||
ports => $ports,
|
||||
server_names => $facts['networking']['hostname'],
|
||||
ipaddresses => $facts['networking']['ip'],
|
||||
options => $options,
|
||||
tag => $balancemember_tag,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# profiles::haproxy::certlist
|
||||
class profiles::haproxy::certlist (
|
||||
Boolean $enabled = true,
|
||||
Stdlib::Absolutepath $path = '/etc/haproxy/certificate.list',
|
||||
Array[Stdlib::Absolutepath] $certificates = []
|
||||
) {
|
||||
|
||||
if $enabled {
|
||||
file { $path:
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0600',
|
||||
content => template('profiles/haproxy/certificate.list.erb')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# profiles::haproxy::dns
|
||||
class profiles::haproxy::dns (
|
||||
Array[Stdlib::Fqdn] $cnames = [],
|
||||
Integer $order = 10,
|
||||
){
|
||||
|
||||
# create an A record for each load balancer in a region
|
||||
$location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}"
|
||||
profiles::dns::record { "${facts['networking']['fqdn']}_${location_environment}-halb_A":
|
||||
value => $::facts['networking']['ip'],
|
||||
type => 'A',
|
||||
record => "${location_environment}-halb",
|
||||
zone => $::facts['networking']['domain'],
|
||||
order => $order,
|
||||
}
|
||||
|
||||
# export cnames for haproxy applications
|
||||
$cnames.each |$cname| {
|
||||
profiles::dns::record { "${::facts['networking']['fqdn']}_${cname}_CNAME":
|
||||
value => "${location_environment}-halb",
|
||||
type => 'CNAME',
|
||||
record => "${cname}.",
|
||||
zone => $::facts['networking']['domain'],
|
||||
order => $order,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# profiles::haproxy::frontends
|
||||
class profiles::haproxy::frontends {
|
||||
|
||||
# for each frontend:
|
||||
$frontends = lookup('profiles::haproxy::frontends', Hash, 'deep', {})
|
||||
$frontends.each |$frontend, $data| {
|
||||
|
||||
# create frontends
|
||||
haproxy::frontend { $frontend:
|
||||
* => $data,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# profiles::haproxy::listeners
|
||||
class profiles::haproxy::listeners {
|
||||
# set location_environment
|
||||
$location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}"
|
||||
|
||||
# for each listener:
|
||||
$listeners = lookup('profiles::haproxy::listeners', Hash, 'deep', {})
|
||||
$listeners.each |$listen, $data| {
|
||||
|
||||
# create listener
|
||||
haproxy::listen { $listen:
|
||||
* => $data,
|
||||
}
|
||||
|
||||
# collect exported resources
|
||||
$tag = "${listen}_${location_environment}"
|
||||
Haproxy::Balancermember <<| tag == $tag |>>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# the default status listener
|
||||
class profiles::haproxy::ls_stats (
|
||||
Stdlib::IP::Address $bind_addr = $facts['networking']['ip'],
|
||||
Stdlib::Port $bind_port = 9090,
|
||||
Array $bind_opts = [],
|
||||
String $user = 'admin',
|
||||
String $pass = 'admin',
|
||||
) {
|
||||
haproxy::listen { 'stats':
|
||||
bind => { "${bind_addr}:${bind_port}" => $bind_opts },
|
||||
options => {
|
||||
'mode' => 'http',
|
||||
'stats' => [
|
||||
'uri /',
|
||||
"auth ${user}:${pass}",
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# profiles::haproxy::mappings
|
||||
class profiles::haproxy::mappings {
|
||||
|
||||
# for each mapping:
|
||||
$mappings = lookup('profiles::haproxy::mappings')
|
||||
$mappings.each |$mapping, $data| {
|
||||
|
||||
# create mapping
|
||||
haproxy::mapfile { $mapping:
|
||||
* => $data,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# profiles::haproxy::selinux
|
||||
class profiles::haproxy::selinux (
|
||||
Array[String] $sebooleans = [],
|
||||
Array[Stdlib::Port] $ports = [],
|
||||
) {
|
||||
|
||||
# manage enforcing mode
|
||||
include profiles::selinux::setenforce
|
||||
|
||||
# manage selinux requirements for haproxy
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
# set context for ports
|
||||
$ports.each |$port| {
|
||||
selinux::port { "haproxy_port_${port}":
|
||||
ensure => 'present',
|
||||
seltype => 'http_port_t',
|
||||
protocol => 'tcp',
|
||||
port => $port,
|
||||
}
|
||||
}
|
||||
|
||||
# enable sebooleans
|
||||
$sebooleans.each |$bool| {
|
||||
selboolean { $bool:
|
||||
value => on,
|
||||
persistent => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# configure a haproxy server
|
||||
class profiles::haproxy::server (
|
||||
Hash $globals = {},
|
||||
Hash $defaults = {},
|
||||
){
|
||||
|
||||
# default global/defaults arrays
|
||||
$global_options = {
|
||||
'log' => "${facts['networking']['ip']} local0",
|
||||
'chroot' => '/var/lib/haproxy',
|
||||
'pidfile' => '/var/run/haproxy.pid',
|
||||
'maxconn' => '4000',
|
||||
'user' => 'haproxy',
|
||||
'group' => 'haproxy',
|
||||
'daemon' => '',
|
||||
'stats' => 'socket /var/lib/haproxy/stats',
|
||||
}
|
||||
$default_options = {
|
||||
'log' => 'global',
|
||||
'stats' => 'enable',
|
||||
'option' => ['redispatch'],
|
||||
'retries' => '3',
|
||||
'timeout' => [
|
||||
'http-request 10s',
|
||||
'queue 1m',
|
||||
'connect 10s',
|
||||
'client 1m',
|
||||
'server 1m',
|
||||
'check 10s',
|
||||
],
|
||||
'maxconn' => '8000',
|
||||
}
|
||||
|
||||
# merge the default globals/defaults with those provided as params
|
||||
$merged_global_options = merge($global_options, $globals)
|
||||
$merged_default_options = merge($default_options, $defaults)
|
||||
|
||||
# wait until enc_role matches haproxy enc_role
|
||||
if $facts['enc_role'] == 'roles::infra::halb::haproxy' {
|
||||
|
||||
# manage selinux
|
||||
include profiles::haproxy::selinux
|
||||
|
||||
# create the haproxy service/instance
|
||||
class { 'haproxy':
|
||||
global_options => $merged_global_options,
|
||||
defaults_options => $merged_default_options,
|
||||
require => Class['profiles::haproxy::selinux']
|
||||
}
|
||||
|
||||
include profiles::haproxy::certlist # manage the certificate list file
|
||||
include profiles::haproxy::mappings # manage the domain to backend mappings
|
||||
include profiles::haproxy::ls_stats # default status listener
|
||||
include profiles::haproxy::dns # manage dns for haproxy
|
||||
include profiles::haproxy::frontends # create frontends
|
||||
include profiles::haproxy::backends # create backends
|
||||
include profiles::haproxy::listeners # create listeners
|
||||
|
||||
Class['profiles::haproxy::certlist']
|
||||
-> Class['profiles::haproxy::dns']
|
||||
-> Class['profiles::haproxy::mappings']
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
# profiles::helpers::certmanager
|
||||
#
|
||||
# wrapper class for python, pip and venv
|
||||
class profiles::helpers::certmanager (
|
||||
String $script_name = 'certmanager',
|
||||
Stdlib::AbsolutePath $base_path = "/opt/${script_name}",
|
||||
Stdlib::AbsolutePath $venv_path = "${base_path}/venv",
|
||||
Stdlib::AbsolutePath $config_path = "${base_path}/config.yaml",
|
||||
Hash $vault_config = {},
|
||||
String $owner = 'root',
|
||||
String $group = 'root',
|
||||
Boolean $systempkgs = false,
|
||||
String $version = 'system',
|
||||
Array[String[1]] $packages = ['requests', 'pyyaml'],
|
||||
){
|
||||
|
||||
if $::facts['python3_version'] {
|
||||
|
||||
$python_version = $version ? {
|
||||
'system' => $::facts['python3_version'],
|
||||
default => $version,
|
||||
}
|
||||
|
||||
# ensure the base_path exists
|
||||
file { $base_path:
|
||||
ensure => directory,
|
||||
mode => '0755',
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
}
|
||||
|
||||
# create a venv
|
||||
python::pyvenv { $venv_path :
|
||||
ensure => present,
|
||||
version => $python_version,
|
||||
systempkgs => $systempkgs,
|
||||
venv_dir => $venv_path,
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
require => File[$base_path],
|
||||
}
|
||||
|
||||
# install the required pip packages
|
||||
$packages.each |String $package| {
|
||||
python::pip { "${venv_path}_${package}":
|
||||
ensure => present,
|
||||
pkgname => $package,
|
||||
virtualenv => $venv_path,
|
||||
}
|
||||
}
|
||||
|
||||
# create the script from a template
|
||||
file { "${base_path}/${script_name}":
|
||||
ensure => file,
|
||||
mode => '0755',
|
||||
content => template("profiles/helpers/${script_name}.erb"),
|
||||
require => Python::Pyvenv[$venv_path],
|
||||
}
|
||||
|
||||
# create the config from a template
|
||||
file { $config_path:
|
||||
ensure => file,
|
||||
mode => '0660',
|
||||
owner => 'puppet',
|
||||
group => 'root',
|
||||
content => Sensitive(template("profiles/helpers/${script_name}_config.yaml.erb")),
|
||||
require => Python::Pyvenv[$venv_path],
|
||||
}
|
||||
|
||||
# create symbolic link in $PATH
|
||||
file { "/usr/local/bin/${script_name}":
|
||||
ensure => 'link',
|
||||
target => "${base_path}/${script_name}",
|
||||
require => File["${base_path}/${script_name}"],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,45 +12,54 @@ class profiles::helpers::node_lookup (
|
||||
Array[String[1]] $packages = ['requests'],
|
||||
){
|
||||
|
||||
# ensure the base_path exists
|
||||
file { $base_path:
|
||||
ensure => directory,
|
||||
mode => '0755',
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
}
|
||||
# create a venv
|
||||
python::pyvenv { $venv_path :
|
||||
ensure => present,
|
||||
version => $version,
|
||||
systempkgs => $systempkgs,
|
||||
venv_dir => $venv_path,
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
require => File[$base_path],
|
||||
}
|
||||
if $::facts['python3_version'] {
|
||||
|
||||
# install the required pip packages
|
||||
$packages.each |String $package| {
|
||||
python::pip { "${venv_path}_${package}":
|
||||
$python_version = $version ? {
|
||||
'system' => $::facts['python3_version'],
|
||||
default => $version,
|
||||
}
|
||||
|
||||
# ensure the base_path exists
|
||||
file { $base_path:
|
||||
ensure => directory,
|
||||
mode => '0755',
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
}
|
||||
|
||||
# create a venv
|
||||
python::pyvenv { $venv_path :
|
||||
ensure => present,
|
||||
pkgname => $package,
|
||||
virtualenv => $venv_path,
|
||||
version => $python_version,
|
||||
systempkgs => $systempkgs,
|
||||
venv_dir => $venv_path,
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
require => File[$base_path],
|
||||
}
|
||||
|
||||
# install the required pip packages
|
||||
$packages.each |String $package| {
|
||||
python::pip { "${venv_path}_${package}":
|
||||
ensure => present,
|
||||
pkgname => $package,
|
||||
virtualenv => $venv_path,
|
||||
}
|
||||
}
|
||||
|
||||
# create the script from a template
|
||||
file { "${base_path}/${script_name}":
|
||||
ensure => file,
|
||||
mode => '0755',
|
||||
content => template("profiles/helpers/${script_name}.erb"),
|
||||
require => Python::Pyvenv[$venv_path],
|
||||
}
|
||||
|
||||
# create symbolic link in $PATH
|
||||
file { "/usr/local/bin/${script_name}":
|
||||
ensure => 'link',
|
||||
target => "${base_path}/${script_name}",
|
||||
require => File["${base_path}/${script_name}"],
|
||||
}
|
||||
}
|
||||
|
||||
# create the script from a template
|
||||
file { "${base_path}/${script_name}":
|
||||
ensure => file,
|
||||
mode => '0755',
|
||||
content => template("profiles/helpers/${script_name}.erb"),
|
||||
require => Python::Pyvenv[$venv_path],
|
||||
}
|
||||
|
||||
# create symbolic link in $PATH
|
||||
file { "/usr/local/bin/${script_name}":
|
||||
ensure => 'link',
|
||||
target => "${base_path}/${script_name}",
|
||||
require => File["${base_path}/${script_name}"],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
# profiles::minio::server
|
||||
class profiles::minio::server (
|
||||
String $minio_root_user,
|
||||
String $minio_root_pass,
|
||||
Array $minio_opts = [],
|
||||
Boolean $minio_members_lookup = false,
|
||||
String $minio_members_role = undef,
|
||||
Integer $minio_members = undef,
|
||||
Array $minio_servers = [],
|
||||
String $minio_storage_class = 'EC:2',
|
||||
String $version = 'RELEASE.2023-12-20T01-00-02Z',
|
||||
String $checksum = '09fafaf399885b4912bafda6fa03fc4ccbc39ec45e17239677217317915d6aeb',
|
||||
String $checksum_type = 'sha256',
|
||||
String $owner = 'minio',
|
||||
String $group = 'minio',
|
||||
Stdlib::Fqdn $url_domain = $::facts['networking']['domain'],
|
||||
Enum['http', 'https'] $url_scheme = 'http',
|
||||
Array[String[0]] $blockdev = [],
|
||||
Stdlib::Port $listen_port = 9000,
|
||||
Stdlib::IP::Address $listen_addr = $::facts['networking']['ip'],
|
||||
Stdlib::AbsolutePath $datadir = '/data/minio',
|
||||
Stdlib::AbsolutePath $confdir = '/etc/minio',
|
||||
Stdlib::AbsolutePath $homedir = '/var/lib/minio',
|
||||
Stdlib::AbsolutePath $bindir = '/opt/minio',
|
||||
Optional[Enum['puppet']] $cert_type = 'puppet',
|
||||
) {
|
||||
|
||||
# create the region string
|
||||
$minio_region = "${::facts['country']}-${::facts['region']}"
|
||||
|
||||
# count the block devices
|
||||
$blockdev_count = count($blockdev)
|
||||
|
||||
# create minio static facts, which are used by pre-compile facts
|
||||
file { "${lookup('facts_path')}/minio_facts.yaml":
|
||||
ensure => file,
|
||||
content => template('profiles/minio/minio_facts.yaml.erb'),
|
||||
}
|
||||
|
||||
# create the user if its not yet initialised, if it is initialised, let the minio::server class manage
|
||||
# manage the resource. This is done so that the user/group exist before attempting to create the data-
|
||||
# directories.
|
||||
if ! $::facts['minio_user_exists'] {
|
||||
class {'minio::server::user':
|
||||
manage_user => true,
|
||||
manage_group => true,
|
||||
manage_home => true,
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
home => $homedir,
|
||||
}
|
||||
}
|
||||
|
||||
# create the datadir
|
||||
if ! $::facts['minio_datadirs_initialised'] {
|
||||
|
||||
# create the datadir root
|
||||
exec { "mkdir_p_${datadir}":
|
||||
command => "mkdir -p '${datadir}'",
|
||||
unless => "test -d '${datadir}'",
|
||||
path => '/bin:/usr/bin',
|
||||
}
|
||||
|
||||
# create te datavol's if blockdev's are listed
|
||||
$blockdev.each |Integer $index, String $device| {
|
||||
$id = $index + 1
|
||||
profiles::storage::datavol {"${::facts['networking']['fqdn']}_${device}":
|
||||
fstype => 'xfs',
|
||||
vg => "minio_vg${id}",
|
||||
pv => $device,
|
||||
lv => "store${id}",
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
mount => "${datadir}/store${id}",
|
||||
require => Exec["mkdir_p_${datadir}"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# copy puppet certs to /etc/pki/tls/puppet
|
||||
include profiles::pki::puppetcerts
|
||||
|
||||
# create the cert configuration hash
|
||||
if $cert_type == 'puppet' {
|
||||
$cert_conf = {
|
||||
'source_path' => '/etc/pki/tls/puppet',
|
||||
'source_cert_name' => $::facts['networking']['fqdn'],
|
||||
'source_key_name' => $::facts['networking']['fqdn'],
|
||||
}
|
||||
}
|
||||
|
||||
# if lookup is enabled, find all the hosts in the specified role and create the servers_array
|
||||
if $minio_members_lookup {
|
||||
|
||||
# check that the role is also set
|
||||
unless !($minio_members_role == undef) {
|
||||
fail("minio_members_role must be provided for ${title} when minio_members_lookup is True")
|
||||
}
|
||||
|
||||
# if it is, find hosts, sort them so they dont cause changes every run
|
||||
#$servers_array = sort(query_nodes("enc_role='${minio_members_role}'", 'networking.fqdn'))
|
||||
$servers_array = sort(query_nodes("enc_role='${minio_members_role}' and minio_region='${minio_region}'", 'networking.fqdn'))
|
||||
|
||||
# else use provided array from params
|
||||
}else{
|
||||
$servers_array = $minio_servers
|
||||
}
|
||||
|
||||
# iterate through the servers_array and find the nodeid for each host
|
||||
$servers_array.each |Integer $index, String $server| {
|
||||
$id = $index + 1
|
||||
if $::facts['networking']['fqdn'] == $server {
|
||||
$nodeid = $id
|
||||
if $::facts['minio_pool'] != undef {
|
||||
|
||||
# create a cname which is used to create a sequential group of names for distributed minio pool
|
||||
profiles::dns::record { "${minio_region}-${::facts['minio_pool']}-${nodeid}.${::facts['networking']['domain']}_CNAME":
|
||||
value => $::facts['networking']['hostname'],
|
||||
type => 'CNAME',
|
||||
record => "${minio_region}-${::facts['minio_pool']}-${nodeid}.${::facts['networking']['domain']}.",
|
||||
zone => $::facts['networking']['domain'],
|
||||
order => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# wait until all expected servers in the pool have reported into puppet
|
||||
if count($servers_array) == $::facts['minio_members'] and $::facts['minio_pool'] != undef {
|
||||
|
||||
# if datadirs and user have been initialised, prepare configuration.
|
||||
if $::facts['minio_datadirs_initialised'] and $::facts['minio_user_exists'] {
|
||||
|
||||
# join the minio_opts
|
||||
$options = join($minio_opts, ' ')
|
||||
|
||||
# create vars for $deployment_definition, others used below are params
|
||||
$url_location = "${minio_region}-${::facts['minio_pool']}"
|
||||
$url_servers = "1...${count($servers_array)}"
|
||||
|
||||
# create the deployment definition line
|
||||
# >= 1 : https://au-somewhere-1-pool1-{1...5}.example.domain/var/minio/store{1...4}
|
||||
# == 1 : https://au-somewhere-1-pool1-{1...5}.example.domain/var/minio/store1
|
||||
# else : https://au-somewhere-1-pool1-{1...5}.example.domain/var/minio
|
||||
if $blockdev_count >= 1 {
|
||||
$deployment_definition = "${url_scheme}://${url_location}-{${url_servers}}.${url_domain}:${listen_port}${datadir}/store{1...${blockdev_count}}"
|
||||
}elsif $blockdev_count == 1 {
|
||||
$deployment_definition = "${url_scheme}://${url_location}-{${url_servers}}.${url_domain}:${listen_port}${datadir}/store1"
|
||||
}else{
|
||||
$deployment_definition = "${url_scheme}://${url_location}-{${url_servers}}.${url_domain}:${listen_port}${datadir}"
|
||||
}
|
||||
|
||||
# create the configuration hash
|
||||
$configuration = {
|
||||
'MINIO_ROOT_USER' => $minio_root_user,
|
||||
'MINIO_ROOT_PASSWORD' => $minio_root_pass.unwrap,
|
||||
'MINIO_REGION_NAME' => $minio_region,
|
||||
'MINIO_OPTS' => "\'${options}\'",
|
||||
'MINIO_DEPLOYMENT_DEFINITION' => $deployment_definition,
|
||||
'MINIO_STORAGE_CLASS_STANDARD' => $minio_storage_class,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check all the expected DNS CNAME records do not exist
|
||||
$all_dns_exist = $::facts['minio_pool_dns'].all |String $cname, Boolean $exists| { $exists }
|
||||
|
||||
# create the minio server if all dns records exist
|
||||
if $all_dns_exist {
|
||||
class { 'minio::server::install':
|
||||
package_ensure => 'present',
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
base_url => 'https://dl.minio.io/server/minio/release',
|
||||
version => $version,
|
||||
checksum => $checksum,
|
||||
checksum_type => $checksum_type,
|
||||
configuration_directory => $confdir,
|
||||
installation_directory => $bindir,
|
||||
storage_root => $datadir,
|
||||
listen_ip => $listen_addr,
|
||||
listen_port => $listen_port,
|
||||
manage_service => true,
|
||||
service_template => 'profiles/minio/minio.service.erb',
|
||||
service_provider => 'systemd',
|
||||
cert_directory => "${confdir}/certs",
|
||||
custom_configuration_file_path => '/etc/default/minio',
|
||||
}
|
||||
|
||||
class { 'minio::server::config':
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
configuration_directory => $confdir,
|
||||
installation_directory => $bindir,
|
||||
storage_root => $datadir,
|
||||
configuration => $configuration,
|
||||
custom_configuration_file_path => '/etc/default/minio',
|
||||
require => Class['Minio::Server::Install'],
|
||||
}
|
||||
|
||||
class { 'minio::server::service':
|
||||
manage_service => true,
|
||||
service_provider => 'systemd',
|
||||
service_ensure => 'running',
|
||||
require => Class['Minio::Server::Config'],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
# profiles::nginx:simpleproxy
|
||||
#
|
||||
# only one simpleproxy per host, for anything more advanced, use nginx class
|
||||
class profiles::nginx::simpleproxy (
|
||||
Stdlib::Fqdn $nginx_vhost = 'localhost',
|
||||
Array[Stdlib::Host] $nginx_aliases = [],
|
||||
Stdlib::Port $nginx_port = 80,
|
||||
Stdlib::Port $nginx_ssl_port = 443,
|
||||
Enum['http','https','both'] $nginx_listen_mode = 'https',
|
||||
Enum['puppet', 'vault'] $nginx_cert_type = 'vault',
|
||||
Enum['http','https'] $proxy_scheme = 'http',
|
||||
Stdlib::Port $proxy_port = 80,
|
||||
Stdlib::Host $proxy_host = $facts['networking']['ip'],
|
||||
String $proxy_path = '/',
|
||||
) {
|
||||
|
||||
# if nginx_version isnt set, install nginx
|
||||
if ! $facts['nginx_version'] {
|
||||
package {'nginx':
|
||||
ensure => 'present',
|
||||
}
|
||||
|
||||
# else, configure simple proxy
|
||||
}else{
|
||||
|
||||
# build the proxyurl from proxy_* variables
|
||||
$proxyurl = "${proxy_scheme}://${proxy_host}:${proxy_port}${proxy_path}"
|
||||
|
||||
# set the server_names
|
||||
$server_names = unique([$facts['networking']['fqdn'], $nginx_vhost] + $nginx_aliases)
|
||||
|
||||
# select the certificates to use based on cert type
|
||||
case $nginx_cert_type {
|
||||
'puppet': {
|
||||
$selected_ssl_cert = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt"
|
||||
$selected_ssl_key = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key"
|
||||
}
|
||||
'vault': {
|
||||
$selected_ssl_cert = '/etc/pki/tls/vault/certificate.crt'
|
||||
$selected_ssl_key = '/etc/pki/tls/vault/private.key'
|
||||
}
|
||||
default: {
|
||||
# enum param prevents this ever being reached
|
||||
}
|
||||
}
|
||||
|
||||
# set variables based on the listen_mode
|
||||
case $nginx_listen_mode {
|
||||
'http': {
|
||||
$enable_ssl = false
|
||||
$ssl_cert = undef
|
||||
$ssl_key = undef
|
||||
$listen_port = $nginx_port
|
||||
$listen_ssl_port = undef
|
||||
$extras_hash = {}
|
||||
}
|
||||
'https': {
|
||||
$enable_ssl = true
|
||||
$ssl_cert = $selected_ssl_cert
|
||||
$ssl_key = $selected_ssl_key
|
||||
$listen_port = $nginx_ssl_port
|
||||
$listen_ssl_port = $nginx_ssl_port
|
||||
$extras_hash = {
|
||||
'subscribe' => [File[$ssl_cert], File[$ssl_key]],
|
||||
}
|
||||
}
|
||||
'both': {
|
||||
$enable_ssl = true
|
||||
$ssl_cert = $selected_ssl_cert
|
||||
$ssl_key = $selected_ssl_key
|
||||
$listen_port = $nginx_port
|
||||
$listen_ssl_port = $nginx_ssl_port
|
||||
$extras_hash = {
|
||||
'subscribe' => [File[$ssl_cert], File[$ssl_key]],
|
||||
}
|
||||
}
|
||||
default: {
|
||||
# enum param prevents this ever being reached
|
||||
}
|
||||
}
|
||||
|
||||
# define the default parameters for the nginx server
|
||||
$defaults = {
|
||||
'listen_port' => $listen_port,
|
||||
'server_name' => $server_names,
|
||||
'use_default_location' => true,
|
||||
'access_log' => "/var/log/nginx/${nginx_vhost}_access.log",
|
||||
'error_log' => "/var/log/nginx/${nginx_vhost}_error.log",
|
||||
'autoindex' => 'on',
|
||||
'ssl' => $enable_ssl,
|
||||
'ssl_cert' => $ssl_cert,
|
||||
'ssl_key' => $ssl_key,
|
||||
'ssl_port' => $listen_ssl_port,
|
||||
'proxy' => $proxyurl,
|
||||
}
|
||||
|
||||
# merge the hashes conditionally
|
||||
$nginx_parameters = merge($defaults, $extras_hash)
|
||||
|
||||
# manage the nginx class
|
||||
include 'nginx'
|
||||
|
||||
# create the nginx vhost with the merged parameters
|
||||
create_resources('nginx::resource::server', { $nginx_vhost => $nginx_parameters })
|
||||
|
||||
# manage selinux
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
# make sure nginx can reverse proxy
|
||||
selboolean { 'httpd_can_network_connect':
|
||||
persistent => true,
|
||||
value => 'on',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,11 @@ class profiles::ntp::client (
|
||||
'running',
|
||||
'stopped'
|
||||
] $wait_ensure = 'running',
|
||||
Enum[
|
||||
'all',
|
||||
'region',
|
||||
'country'
|
||||
] $use_ntp = 'all',
|
||||
Boolean $client_only = true,
|
||||
) {
|
||||
|
||||
@@ -18,23 +23,25 @@ class profiles::ntp::client (
|
||||
# through the profiles::ntp::server class.
|
||||
if $client_only {
|
||||
|
||||
# if ntp_role is set, find all hosts matching that enc_role
|
||||
if $ntp_role == undef {
|
||||
$ntpserver_array = $peers
|
||||
}else{
|
||||
$ntpserver_array = query_nodes("enc_role='${ntp_role}'", 'networking.fqdn')
|
||||
$ntpserver_array = $ntp_role ? {
|
||||
undef => $peers,
|
||||
default => $use_ntp ? {
|
||||
'all' => query_nodes("enc_role='${ntp_role}'", 'networking.fqdn'),
|
||||
'region' => query_nodes("enc_role='${ntp_role}' and region=${facts['region']}", 'networking.fqdn'),
|
||||
'country' => query_nodes("enc_role='${ntp_role}' and country=${facts['country']}", 'networking.fqdn'),
|
||||
}
|
||||
}
|
||||
|
||||
# Define the client configuration based on OS family
|
||||
if $facts['os']['family'] == 'RedHat' {
|
||||
class { 'chrony':
|
||||
servers => $ntpserver_array,
|
||||
servers => sort($ntpserver_array),
|
||||
wait_enable => $wait_enable,
|
||||
wait_ensure => $wait_ensure,
|
||||
}
|
||||
} else {
|
||||
class { 'chrony':
|
||||
servers => $ntpserver_array,
|
||||
servers => sort($ntpserver_array),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# profiles::ovirt::node
|
||||
class profiles::ovirt::node {
|
||||
# Define the DNF modules to be enabled
|
||||
$dnf_modules_to_enable = {
|
||||
'javapackages-tools' => { 'ensure' => 'latest' },
|
||||
'pki-deps' => { 'ensure' => 'latest' },
|
||||
'postgresql' => { 'ensure' => '12' },
|
||||
'mod_auth_openidc' => { 'ensure' => '2.3' },
|
||||
'nodejs' => { 'ensure' => '14' },
|
||||
}
|
||||
|
||||
# Enable the DNF modules
|
||||
create_resources(
|
||||
'package',
|
||||
$dnf_modules_to_enable, {
|
||||
provider => dnfmodule,
|
||||
enable_only => true
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# This class manages the installation of packages for the base profile
|
||||
#
|
||||
# Parameters:
|
||||
# - $install: An array of package names to be installed
|
||||
# - $remove: An array of package names to be removed
|
||||
#
|
||||
class profiles::packages (
|
||||
Array $install = [],
|
||||
Array $install_exclude = [],
|
||||
Array $remove = [],
|
||||
Array $remove_exclude = [],
|
||||
) {
|
||||
|
||||
# Filter out excluded packages
|
||||
$install_real = $install.filter |$item| { !$install_exclude.any |$exclude_item| { $exclude_item == $item } }
|
||||
$remove_real = $remove.filter |$item| { !$remove_exclude.any |$exclude_item| { $exclude_item == $item } }
|
||||
|
||||
# Ensure packages to install are installed
|
||||
ensure_packages($install_real, {'ensure' => 'present'})
|
||||
|
||||
# Ensure packages to remove are absent
|
||||
ensure_packages($remove_real, {'ensure' => 'absent'})
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
# This class manages the installation of packages for the base profile
|
||||
#
|
||||
# Parameters:
|
||||
# - $add: An array of package names to be installed
|
||||
# - $remove: An array of package names to be removed
|
||||
#
|
||||
class profiles::packages::base (
|
||||
Array $add = [],
|
||||
Array $remove = [],
|
||||
) {
|
||||
|
||||
# Ensure packages to add are installed
|
||||
ensure_packages($add, {'ensure' => 'present'})
|
||||
|
||||
# Ensure packages to remove are absent
|
||||
$remove.each |String $package| {
|
||||
package { $package:
|
||||
ensure => 'absent',
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# installs git related packages
|
||||
#
|
||||
class profiles::packages::git (
|
||||
Array[String] $packages = lookup('profiles::packages::git', Array, 'first', ['git']),
|
||||
) {
|
||||
$packages.each |String $package| {
|
||||
package { $package:
|
||||
ensure => installed,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# installs reposync related packages
|
||||
#
|
||||
class profiles::packages::reposync (
|
||||
Array[String] $packages = lookup('profiles::packages::reposync', Array, 'first', ['createrepo']),
|
||||
) {
|
||||
$packages.each |String $package| {
|
||||
package { $package:
|
||||
ensure => installed,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# installs selinux related packages
|
||||
#
|
||||
class profiles::packages::selinux (
|
||||
Array[String] $packages = lookup('profiles::packages::selinux', Array, 'first', ['policycoreutils']),
|
||||
) {
|
||||
$packages.each |String $package| {
|
||||
package { $package:
|
||||
ensure => installed,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
# profiles::pki::puppetcerts
|
||||
class profiles::pki::puppetcerts {
|
||||
|
||||
# Define the directory
|
||||
file { '/etc/pki/tls/puppet':
|
||||
ensure => 'directory',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
}
|
||||
|
||||
# Copy the CA certificate
|
||||
file { '/etc/pki/tls/puppet/ca.pem':
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
source => '/etc/puppetlabs/puppet/ssl/certs/ca.pem',
|
||||
require => File['/etc/pki/tls/puppet'],
|
||||
}
|
||||
|
||||
# Copy the private key
|
||||
file { "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key":
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
source => "/etc/puppetlabs/puppet/ssl/private_keys/${facts['networking']['fqdn']}.pem",
|
||||
require => File['/etc/pki/tls/puppet'],
|
||||
}
|
||||
|
||||
# Copy the certificate
|
||||
$cert = "/etc/puppetlabs/puppet/ssl/certs/${facts['networking']['fqdn']}.pem"
|
||||
file { "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt":
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
source => "/etc/puppetlabs/puppet/ssl/certs/${facts['networking']['fqdn']}.pem",
|
||||
require => File['/etc/pki/tls/puppet'],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
# profiles::pki::vault
|
||||
class profiles::pki::vault (
|
||||
Optional[Array[Stdlib::Host]] $alt_names = [],
|
||||
Optional[Array[Stdlib::IP::Address]] $ip_sans = [],
|
||||
){
|
||||
|
||||
# validate and prepare additional alt_names, if any
|
||||
$default_alt_names = [$::facts['networking']['hostname'], $::facts['networking']['fqdn']]
|
||||
$effective_alt_names = $alt_names ? {
|
||||
[] => $default_alt_names,
|
||||
default => concat($default_alt_names, $alt_names),
|
||||
}
|
||||
|
||||
# validate and prepare additional ip_sans, if any
|
||||
$default_ip_sans = ['127.0.0.1', $::facts['networking']['ip']]
|
||||
$effective_ip_sans = $ip_sans ? {
|
||||
[] => $default_ip_sans,
|
||||
default => concat($default_ip_sans, $ip_sans),
|
||||
}
|
||||
|
||||
# path for the alt names file
|
||||
$base_path = '/etc/pki/tls/vault'
|
||||
$alt_names_file = "${base_path}/alt_names"
|
||||
|
||||
# ensure the base directory exists
|
||||
file { '/etc/pki':
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
}
|
||||
file { '/etc/pki/tls':
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
require => File['/etc/pki']
|
||||
}
|
||||
file { $base_path:
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
require => File['/etc/pki/tls']
|
||||
}
|
||||
|
||||
# alt_names_file contents
|
||||
$alt_names_content = concat($effective_alt_names, $effective_ip_sans)
|
||||
|
||||
# manage the alt names file
|
||||
file { $alt_names_file:
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
content => join($alt_names_content, "\n"),
|
||||
require => File[$base_path]
|
||||
}
|
||||
|
||||
# compare the sorted arrays of altnames from disk (fact) vs what is intended (this run)
|
||||
$alt_names_match = sort($::facts['vault_cert_altnames']) == sort($alt_names_content)
|
||||
|
||||
# only renew certificate if its expiring or the alt names have changed
|
||||
if $::facts['vault_cert_expiring'] or ! $alt_names_match {
|
||||
|
||||
# certificate variables
|
||||
$common_name = $::facts['networking']['fqdn']
|
||||
$valid_days = 90
|
||||
|
||||
# prepare alt_names and ip_sans arguments conditionally
|
||||
$alt_names_string = $effective_alt_names.empty() ? {
|
||||
true => '',
|
||||
default => join($effective_alt_names, ','),
|
||||
}
|
||||
$ip_sans_string = $effective_ip_sans.empty() ? {
|
||||
true => '',
|
||||
default => join($effective_ip_sans, ','),
|
||||
}
|
||||
|
||||
# certmanager arguments
|
||||
$cmd = '/usr/local/bin/certmanager'
|
||||
$alt_names_arg = '--alt-names'
|
||||
$ip_sans_arg = '--ip-sans'
|
||||
$expiry_days_arg = '--expiry-days'
|
||||
|
||||
# call the script with generate(), capturing json output
|
||||
$json_output = generate(
|
||||
$cmd,
|
||||
$common_name,
|
||||
$alt_names_arg,
|
||||
$alt_names_string,
|
||||
$ip_sans_arg,
|
||||
$ip_sans_string,
|
||||
$expiry_days_arg,
|
||||
$valid_days,
|
||||
'--json'
|
||||
)
|
||||
$cert_data = parsejson($json_output)
|
||||
|
||||
# manage certificate file resources based on script output
|
||||
$certificate_files = {
|
||||
"${base_path}/certificate.crt" => $cert_data['certificate'],
|
||||
"${base_path}/private.key" => $cert_data['private_key'],
|
||||
"${base_path}/full_chain.crt" => $cert_data['full_chain'],
|
||||
"${base_path}/ca_certificate.crt" => $cert_data['ca_certificate'],
|
||||
"${base_path}/certificate.pem" => "${cert_data['certificate']}\n${cert_data['private_key']}",
|
||||
}
|
||||
|
||||
# manage each file resources
|
||||
$certificate_files.each |$file_path, $content| {
|
||||
file { $file_path:
|
||||
ensure => file,
|
||||
content => $content,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
require => File[$base_path],
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
# manage each file resources, but dont change the content
|
||||
$certificate_files = [
|
||||
"${base_path}/certificate.crt",
|
||||
"${base_path}/private.key",
|
||||
"${base_path}/full_chain.crt",
|
||||
"${base_path}/ca_certificate.crt",
|
||||
"${base_path}/certificate.pem"
|
||||
]
|
||||
|
||||
$certificate_files.each |$file_path| {
|
||||
file { $file_path:
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
require => File[$base_path],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# ensure the ca certificate for vault is installed everywhere
|
||||
class profiles::pki::vaultca {
|
||||
$root_cacert = 'vaultcaroot.pem'
|
||||
|
||||
# Define the target path based on the operating system
|
||||
case $facts['os']['family'] {
|
||||
'RedHat': {
|
||||
$ca_cert_target_path = "/etc/pki/ca-trust/source/anchors/${root_cacert}"
|
||||
$update_ca_cert_command = 'update-ca-trust extract'
|
||||
}
|
||||
'Debian': {
|
||||
$ca_cert_target_path = "/usr/local/share/ca-certificates/${root_cacert}"
|
||||
$update_ca_cert_command = 'update-ca-certificates'
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported operating system: ${facts['os']['family']}")
|
||||
}
|
||||
}
|
||||
|
||||
# Ensure the CA certificate is present and contains the content from the template
|
||||
file { $ca_cert_target_path:
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
content => template('profiles/pki/vaultcaroot.pem.erb'),
|
||||
notify => Exec['update_ca_trust_store'],
|
||||
}
|
||||
|
||||
# Execute the system command to update the CA trust store
|
||||
exec { 'update_ca_trust_store':
|
||||
command => $update_ca_cert_command,
|
||||
path => ['/bin', '/usr/bin', 'sbin', '/usr/sbin'],
|
||||
refreshonly => true,
|
||||
require => File[$ca_cert_target_path],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# profiles::proxmox::ceph
|
||||
class profiles::proxmox::ceph {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
# localise some vars
|
||||
$network = $profiles::proxmox::params::pve_ceph_network
|
||||
$size = $profiles::proxmox::params::pve_ceph_size
|
||||
$min_size = $profiles::proxmox::params::pve_ceph_minsize
|
||||
|
||||
# install ceph if it is enabled
|
||||
if $profiles::proxmox::params::pve_ceph_install {
|
||||
|
||||
# initialise the cluster, but only on the clusterinit node and only if its not already initialised
|
||||
if $profiles::proxmox::params::pve_clusterinit_master and ! $facts['pve_ceph_initialised']{
|
||||
exec { 'pveceph_init':
|
||||
command => "/usr/bin/pveceph init --network ${network} --size ${size} --min_size ${min_size}",
|
||||
user => 'root',
|
||||
}
|
||||
}
|
||||
|
||||
if $facts['pve_ceph_initialised'] {
|
||||
|
||||
# create monitors
|
||||
if $profiles::proxmox::params::pve_ceph_mon {
|
||||
|
||||
# only when its not already a monitor
|
||||
if ! $facts['is_pveceph_mon'] {
|
||||
exec { 'pveceph_mon':
|
||||
command => '/usr/bin/pveceph mon create',
|
||||
user => 'root',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# create managers
|
||||
if $profiles::proxmox::params::pve_ceph_mgr {
|
||||
|
||||
# only when its not already a manager
|
||||
if ! $facts['is_pveceph_mgr'] {
|
||||
exec { 'pveceph_mgr':
|
||||
command => '/usr/bin/pveceph mgr create',
|
||||
user => 'root',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
# profiles::proxmox::clusterinit
|
||||
class profiles::proxmox::clusterinit {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
# localise some vars
|
||||
$clusterinit_master = $profiles::proxmox::params::pve_clusterinit_master
|
||||
$clustername = $profiles::proxmox::params::pve_cluster
|
||||
$membersrole = $profiles::proxmox::params::pve_members_role
|
||||
|
||||
# if this is the cluster master
|
||||
if $clusterinit_master {
|
||||
|
||||
# and its not a member of a cluster yet
|
||||
if ! $facts['pve_cluster_member'] {
|
||||
|
||||
# initialise a cluster
|
||||
exec {'pve_init_cluster':
|
||||
command => "/usr/bin/pvecm create ${clustername}",
|
||||
unless => 'pvecm status',
|
||||
timeout => 60,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$servers_array = sort(query_nodes(
|
||||
"enc_role='${membersrole}' and country='${facts['country']}' and region='${facts['region']}'",
|
||||
'networking.fqdn'
|
||||
))
|
||||
|
||||
if ! $profiles::proxmox::params::pve_clusterinit_master {
|
||||
if !empty($servers_array) {
|
||||
notify { "Cluster ${profiles::proxmox::params::pve_cluster} detected, proceeding to join...":
|
||||
}
|
||||
} else {
|
||||
notify { "No cluster flag found for ${profiles::proxmox::params::pve_cluster}, not attempting to join":
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
# profiles::proxmox::clusterjoin
|
||||
class profiles::proxmox::clusterjoin {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
# localise some vars
|
||||
$clusterinit_master = $profiles::proxmox::params::pve_clusterinit_master
|
||||
$clustername = $profiles::proxmox::params::pve_cluster
|
||||
$membersrole = $profiles::proxmox::params::pve_members_role
|
||||
$root_password = $profiles::proxmox::params::root_password
|
||||
|
||||
# query puppetdb for list of cluster members
|
||||
$members_array = sort(query_nodes(
|
||||
"enc_role='${membersrole}' and \
|
||||
country='${facts['country']}' and \
|
||||
region='${facts['region']}' and \
|
||||
pve_cluster.cluster_name='${clustername}'",
|
||||
'networking.fqdn'
|
||||
))
|
||||
|
||||
# check if the pve kernerl is running
|
||||
if $facts['kernelrelease'] == $profiles::proxmox::params::pve_kernel_release {
|
||||
|
||||
# if this is the cluster master
|
||||
if $clusterinit_master {
|
||||
|
||||
# there are no cluster members in puppetdb
|
||||
if empty($members_array) {
|
||||
|
||||
# and this host isnt already in a cluster by itself
|
||||
if ! $facts['pve_cluster'] {
|
||||
|
||||
# initialise a cluster
|
||||
exec {'pve_init_cluster':
|
||||
command => "/usr/bin/pvecm create ${clustername}",
|
||||
unless => 'pvecm status',
|
||||
timeout => 60,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# for non-masters
|
||||
if ! $clusterinit_master {
|
||||
|
||||
# if there are already members of the cluster
|
||||
if !empty($members_array) {
|
||||
|
||||
# and this host isnt already in a cluster
|
||||
if ! $facts['pve_cluster'] {
|
||||
|
||||
# create an expect script to join the cluster
|
||||
file { '/usr/local/bin/join_pvecluster.expect':
|
||||
ensure => file,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
content => template('profiles/proxmox/join_pvecluster.erb'),
|
||||
}
|
||||
|
||||
exec { 'pve_join_cluster':
|
||||
command => "/usr/local/bin/join_pvecluster.expect '${root_password.unwrap}' '${members_array[0]}'",
|
||||
require => [File['/usr/local/bin/join_pvecluster.expect'], Package['expect']],
|
||||
unless => "/usr/bin/pvesh nodes | grep -q '${facts['networking']['hostname']}'",
|
||||
user => 'root',
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notify { "No initialised cluster found for ${clustername}, not attempting to join":
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# profiles::proxmox::config
|
||||
class profiles::proxmox::config {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
# localise some vars
|
||||
$clusterinit_master = $profiles::proxmox::params::pve_clusterinit_master
|
||||
|
||||
# create pve_facts file
|
||||
file {'/opt/puppetlabs/facter/facts.d/pve_facts.yaml':
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0600',
|
||||
content => template('profiles/proxmox/pve_facts.yaml.erb')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# proxmox::
|
||||
class profiles::proxmox::init {
|
||||
|
||||
#include profiles::proxmox::params
|
||||
include profiles::proxmox::repos
|
||||
include profiles::proxmox::install
|
||||
include profiles::proxmox::clusterjoin
|
||||
include profiles::proxmox::ceph
|
||||
include profiles::proxmox::config
|
||||
include profiles::proxmox::weblb
|
||||
|
||||
Class['profiles::proxmox::repos']
|
||||
-> Class['profiles::proxmox::install']
|
||||
-> Class['profiles::proxmox::clusterjoin']
|
||||
-> Class['profiles::proxmox::ceph']
|
||||
-> Class['profiles::proxmox::config']
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
# profiles::proxmox::install
|
||||
class profiles::proxmox::install {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
# install the pve kernel
|
||||
package { 'proxmox-default-kernel':
|
||||
ensure => $profiles::proxmox::params::pve_kernel_version,
|
||||
notify => Reboot['after_run'],
|
||||
require => Apt::Source['proxmox'],
|
||||
}
|
||||
|
||||
# reboot into the new kernel
|
||||
reboot { 'after_run':
|
||||
apply => finished,
|
||||
}
|
||||
|
||||
if $facts['kernelrelease'] == $profiles::proxmox::params::pve_kernel_release {
|
||||
|
||||
# install pve
|
||||
ensure_packages($profiles::proxmox::params::pve_packages_install, { ensure => 'present', require => Apt::Source['proxmox']})
|
||||
|
||||
# remove the old linux kernel metapackage
|
||||
ensure_packages($profiles::proxmox::params::pve_packages_remove, { ensure => 'absent' })
|
||||
|
||||
# install ceph package if requested
|
||||
if $profiles::proxmox::params::pve_ceph_install {
|
||||
ensure_packages($profiles::proxmox::params::pve_packages_ceph, { ensure => 'present', require => Apt::Source['ceph'] })
|
||||
}
|
||||
|
||||
# cleanup the old kernel packages
|
||||
exec { 'remove-linux-kernel-packages':
|
||||
command => '/usr/bin/apt-get purge -y $(/usr/bin/dpkg --list | /bin/grep "linux-image-6.1" | /usr/bin/awk \'{ print $2 }\')',
|
||||
onlyif => '/usr/bin/dpkg --list | /bin/grep -q "linux-image-6.1"',
|
||||
path => ['/usr/bin', '/bin', '/sbin'],
|
||||
refreshonly => true,
|
||||
}
|
||||
|
||||
# update grup
|
||||
exec { 'update-grub':
|
||||
command => '/usr/sbin/update-grub',
|
||||
path => ['/usr/bin', '/bin', '/sbin'],
|
||||
refreshonly => true,
|
||||
}
|
||||
|
||||
# update grub after removing kernel packages only
|
||||
Exec['remove-linux-kernel-packages'] ~> Exec['update-grub']
|
||||
|
||||
# prepare for SDN
|
||||
file_line { 'source-network-interfaces-d':
|
||||
path => '/etc/network/interfaces',
|
||||
line => 'source /etc/network/interfaces.d/*',
|
||||
match => '^source /etc/network/interfaces.d/\*$',
|
||||
append_on_no_match => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# profiles::proxmox::params
|
||||
class profiles::proxmox::params (
|
||||
Sensitive[String] $root_password = Sensitive(lookup('profiles::accounts::root::password')),
|
||||
String $pve_members_role = 'roles::infra::proxmox::node',
|
||||
String $pve_kernel_version = '1.0.1',
|
||||
String $pve_kernel_release = '6.5.13-5-pve',
|
||||
String $pve_cluster = "${::facts['country']}-${::facts['region']}",
|
||||
Boolean $pve_clusterinit_master = false,
|
||||
Boolean $pve_ceph_repos = false,
|
||||
Boolean $pve_ceph_install = false,
|
||||
Boolean $pve_ceph_mon = false,
|
||||
Boolean $pve_ceph_mgr = false,
|
||||
Boolean $pve_ceph_osd = false,
|
||||
String $pve_ceph_release = 'quincy',
|
||||
Integer $pve_ceph_size = 3,
|
||||
Integer $pve_ceph_minsize = 2,
|
||||
Variant[
|
||||
Undef,
|
||||
Stdlib::IP::Address::V4::CIDR
|
||||
] $pve_ceph_network = undef,
|
||||
|
||||
Array $pve_packages_install = [
|
||||
'proxmox-ve',
|
||||
'postfix',
|
||||
'open-iscsi',
|
||||
'frr-pythontools',
|
||||
'ksm-control-daemon'
|
||||
],
|
||||
Array $pve_packages_remove = [
|
||||
'os-prober',
|
||||
'linux-image-amd64'
|
||||
],
|
||||
Array $pve_packages_ceph = [
|
||||
'ceph',
|
||||
'ceph-common',
|
||||
'ceph-fuse',
|
||||
'ceph-mds',
|
||||
'ceph-volume',
|
||||
'gdisk',
|
||||
'nvme-cli'
|
||||
],
|
||||
Stdlib::Port $pve_webport = 8006,
|
||||
){
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# profiles::proxmox::repos
|
||||
class profiles::proxmox::repos {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
$codename = $facts['os']['distro']['codename']
|
||||
|
||||
exec { 'download-proxmox-gpg-key':
|
||||
command => "/usr/bin/wget https://enterprise.proxmox.com/debian/proxmox-release-${codename}.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-${codename}.gpg",
|
||||
creates => "/etc/apt/trusted.gpg.d/proxmox-release-${codename}.gpg",
|
||||
path => ['/usr/bin', '/bin'],
|
||||
require => File['/etc/apt/trusted.gpg.d/'],
|
||||
}
|
||||
|
||||
file { '/etc/apt/trusted.gpg.d/':
|
||||
ensure => 'directory',
|
||||
}
|
||||
|
||||
apt::source { 'proxmox':
|
||||
location => 'http://download.proxmox.com/debian/pve',
|
||||
repos => 'pve-no-subscription',
|
||||
include => {
|
||||
src => false,
|
||||
},
|
||||
}
|
||||
|
||||
if $profiles::proxmox::params::pve_ceph_repos {
|
||||
apt::source { 'ceph':
|
||||
location => "http://download.proxmox.com/debian/ceph-${profiles::proxmox::params::pve_ceph_release}",
|
||||
repos => 'no-subscription',
|
||||
include => {
|
||||
src => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# profiles::proxmox::weblb
|
||||
class profiles::proxmox::weblb {
|
||||
|
||||
# include params class
|
||||
include profiles::proxmox::params
|
||||
|
||||
# export haproxy balancemember
|
||||
profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${profiles::proxmox::params::pve_webport}}":
|
||||
service => "be_${facts['country']}${facts['region']}pve_web",
|
||||
ports => [$profiles::proxmox::params::pve_webport],
|
||||
options => [
|
||||
"cookie ${facts['networking']['hostname']}",
|
||||
'ssl',
|
||||
'verify none',
|
||||
'check',
|
||||
'inter 2s',
|
||||
'rise 3',
|
||||
'fall 2',
|
||||
]
|
||||
}
|
||||
profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${profiles::proxmox::params::pve_webport}_api2}":
|
||||
service => "be_${facts['country']}${facts['region']}pve_api",
|
||||
ports => [$profiles::proxmox::params::pve_webport],
|
||||
options => [
|
||||
'ssl',
|
||||
'verify none',
|
||||
'check',
|
||||
'inter 2s',
|
||||
'rise 3',
|
||||
'fall 2',
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,6 @@ class profiles::puppet::agent (
|
||||
String $puppet_version = 'latest',
|
||||
) {
|
||||
|
||||
# Ensure the puppet-agent package is installed and locked to a specific version
|
||||
package { 'puppet-agent':
|
||||
ensure => $puppet_version,
|
||||
}
|
||||
|
||||
# if puppet-version is anything other than latest, set a versionlock
|
||||
$puppet_versionlock_ensure = $puppet_version ? {
|
||||
'latest' => 'absent',
|
||||
@@ -18,9 +13,29 @@ class profiles::puppet::agent (
|
||||
'latest' => undef,
|
||||
default => $puppet_version,
|
||||
}
|
||||
yum::versionlock{'puppet-agent':
|
||||
ensure => $puppet_versionlock_ensure,
|
||||
version => $puppet_versionlock_version,
|
||||
|
||||
case $facts['os']['family'] {
|
||||
'RedHat': {
|
||||
# Ensure the puppet-agent package is installed and locked to a specific version
|
||||
package { 'puppet-agent':
|
||||
ensure => $puppet_version,
|
||||
require => Yumrepo['puppet'],
|
||||
}
|
||||
|
||||
# versionlock puppet-agent
|
||||
yum::versionlock{'puppet-agent':
|
||||
ensure => $puppet_versionlock_ensure,
|
||||
version => $puppet_versionlock_version,
|
||||
}
|
||||
}
|
||||
'Debian': {
|
||||
# Ensure the puppet-agent package is installed and locked to a specific version
|
||||
package { 'puppet-agent':
|
||||
ensure => $puppet_version,
|
||||
require => Class['profiles::apt::puppet7'],
|
||||
}
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
|
||||
# Ensure the puppet service is running
|
||||
|
||||
@@ -4,35 +4,6 @@
|
||||
# based on specified subnet ranges and domain patterns.
|
||||
# It is useful in environments where nodes are dynamically provisioned and
|
||||
# require automatic certificate signing without manual intervention.
|
||||
#
|
||||
# Parameters:
|
||||
# - `subnet_ranges`: An array of IP subnet ranges in CIDR notation.
|
||||
# Nodes with IP addresses within these ranges will have their
|
||||
# certificates autosigned.
|
||||
# Default: []
|
||||
# Example: ['198.18.17.0/24']
|
||||
#
|
||||
# - `domains`: An array of domain patterns.
|
||||
# Nodes with hostnames matching these patterns will have their
|
||||
# certificates autosigned.
|
||||
# Default: []
|
||||
# Example: ['*.main.unkin.net', '*.secondary.unkin.net']
|
||||
#
|
||||
# - `nodes`: An array of specific node names.
|
||||
# Nodes with hostnames matching these will have their
|
||||
# certificates autosigned.
|
||||
# Default: []
|
||||
# Example: ['somenode.main.unkin.net', 'othernode.secondary.unkin.net']
|
||||
# Usage:
|
||||
#
|
||||
# To include this class with custom parameters:
|
||||
# class { 'profiles::puppet::autosign':
|
||||
# subnet_ranges => ['198.18.17.0/24', '198.18.18.0/24'],
|
||||
# domains => ['*.main.unkin.net', '*.dev.unkin.net'],
|
||||
# nodes => ['somenode.main.unkin.net', 'othernode.dev.unkin.net'],
|
||||
# }
|
||||
#
|
||||
# Alternatively, configure subnet ranges and domains through Hiera.
|
||||
class profiles::puppet::autosign (
|
||||
Array[Stdlib::IP::Address::V4::CIDR] $subnet_ranges = [],
|
||||
Array[String[1]] $domains = [],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# site/profile/manifests/puppet/client.pp
|
||||
class profiles::puppet::client (
|
||||
String $dns_alt_names = $trusted['certname'],
|
||||
Array $dns_alt_names = [$trusted['certname']],
|
||||
String $server = 'puppetmaster',
|
||||
String $ca_server = 'puppetca',
|
||||
String $environment = 'develop',
|
||||
@@ -14,14 +14,21 @@ class profiles::puppet::client (
|
||||
Boolean $usecacheonfailure = false,
|
||||
) {
|
||||
|
||||
# Assuming you want to manage puppet.conf with this profile
|
||||
file { '/etc/puppetlabs/puppet/puppet.conf':
|
||||
ensure => 'present',
|
||||
content => template('profiles/puppet/client/puppet.conf.erb'),
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
notify => Service['puppet'],
|
||||
# dont manage puppet.conf if this is a puppetmaster
|
||||
if $facts['enc_role'] != 'roles::infra::puppet::master' {
|
||||
|
||||
|
||||
$dns_alt_names_string = join(sort($dns_alt_names), ',')
|
||||
|
||||
# Assuming you want to manage puppet.conf with this profile
|
||||
file { '/etc/puppetlabs/puppet/puppet.conf':
|
||||
ensure => 'present',
|
||||
content => template('profiles/puppet/client/puppet.conf.erb'),
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
notify => Service['puppet'],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# Class: profiles::puppet::cobbler_enc
|
||||
#
|
||||
# This will deploy the cobbler-enc tool for puppetmasters
|
||||
#
|
||||
# wrapper class for python, pip and venv
|
||||
class profiles::puppet::cobbler_enc (
|
||||
Stdlib::Host $cobbler_hostname,
|
||||
Enum['http','https'] $cobbler_scheme = 'https',
|
||||
String $script_name = 'cobbler-enc',
|
||||
Stdlib::AbsolutePath $base_path = "/opt/${script_name}",
|
||||
Stdlib::AbsolutePath $venv_path = "${base_path}/venv",
|
||||
String $owner = 'root',
|
||||
String $group = 'root',
|
||||
Boolean $systempkgs = false,
|
||||
String $version = 'system',
|
||||
Array[String[1]] $packages = ['sys','requests','pyyaml'],
|
||||
Stdlib::AbsolutePath $trusted_ca_cert = '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem'
|
||||
){
|
||||
|
||||
# set the cobbler url, required for the erb template
|
||||
$cobbler_base_url = "${cobbler_scheme}://${cobbler_hostname}"
|
||||
|
||||
if $::facts['python3_version'] {
|
||||
|
||||
$python_version = $version ? {
|
||||
'system' => $::facts['python3_version'],
|
||||
default => $version,
|
||||
}
|
||||
|
||||
# ensure the base_path exists
|
||||
file { $base_path:
|
||||
ensure => directory,
|
||||
mode => '0755',
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
}
|
||||
|
||||
# create a venv
|
||||
python::pyvenv { $venv_path :
|
||||
ensure => present,
|
||||
version => $python_version,
|
||||
systempkgs => $systempkgs,
|
||||
venv_dir => $venv_path,
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
require => File[$base_path],
|
||||
}
|
||||
|
||||
# install the required pip packages
|
||||
$packages.each |String $package| {
|
||||
python::pip { "${venv_path}_${package}":
|
||||
ensure => present,
|
||||
pkgname => $package,
|
||||
virtualenv => $venv_path,
|
||||
}
|
||||
}
|
||||
|
||||
# create the script from a template
|
||||
file { "${base_path}/${script_name}":
|
||||
ensure => file,
|
||||
mode => '0755',
|
||||
content => template("profiles/puppet/server/${script_name}.erb"),
|
||||
require => [
|
||||
Python::Pyvenv[$venv_path],
|
||||
Package['python3.11']
|
||||
],
|
||||
}
|
||||
|
||||
# create symbolic link in $PATH
|
||||
file { "/usr/local/bin/${script_name}":
|
||||
ensure => 'link',
|
||||
target => "${base_path}/${script_name}",
|
||||
require => File["${base_path}/${script_name}"],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,43 +4,12 @@
|
||||
# systemd service and timer to keep the repository updated every minute.
|
||||
# The Git package is installed if not present, and the repository at the given
|
||||
# location will always reflect the state of the remote Git repository.
|
||||
#
|
||||
# Parameters:
|
||||
# - enc_repo: The URL of the Git repository to clone.
|
||||
#
|
||||
# Actions:
|
||||
# - Ensures the Git package is installed.
|
||||
# - Ensures the /opt/puppetlabs/enc directory is a clone of the given Git repository.
|
||||
# - Creates a helper script '/opt/puppetlabs/bin/git_update' for updating the Git repository.
|
||||
# - Creates a systemd service and timer that runs the git update script every minute.
|
||||
#
|
||||
# Usage:
|
||||
# Directly include the class in your node definitions or classify your nodes
|
||||
# using an ENC or Hiera.
|
||||
# Example:
|
||||
# node 'puppet.example.com' {
|
||||
# class { 'profiles::puppet::enc':
|
||||
# enc_repo => 'https://github.com/user/repo.git',
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Requirements:
|
||||
# - The 'puppet-vcsrepo' module should be installed on your puppetmaster.
|
||||
# - The 'puppet-systemd' module should be installed on your puppetmaster.
|
||||
# - '/opt/puppetlabs/bin/' directory must exist and be writable.
|
||||
# - Puppet master must have access to the specified Git URL.
|
||||
#
|
||||
# Limitations:
|
||||
# This is designed to work on Unix-like systems only.
|
||||
#
|
||||
class profiles::puppet::enc (
|
||||
String $repo,
|
||||
String $release = 'master',
|
||||
Boolean $force = false,
|
||||
) {
|
||||
|
||||
include profiles::packages::git
|
||||
|
||||
vcsrepo { '/opt/puppetlabs/enc':
|
||||
ensure => latest,
|
||||
provider => git,
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# profiles::puppet::eyaml
|
||||
class profiles::puppet::eyaml (
|
||||
String $privatekey = '',
|
||||
String $publickey = '',
|
||||
) {
|
||||
|
||||
# create the /var/lib/puppet/keys directory
|
||||
file { '/var/lib/puppet':
|
||||
ensure => 'directory',
|
||||
owner => 'puppet',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
}
|
||||
file { '/var/lib/puppet/keys':
|
||||
ensure => 'directory',
|
||||
owner => 'puppet',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
require => File['/var/lib/puppet']
|
||||
}
|
||||
# manage the eyaml private key
|
||||
file { '/var/lib/puppet/keys/private_key.pkcs7.pem':
|
||||
ensure => 'file',
|
||||
owner => 'puppet',
|
||||
group => 'root',
|
||||
mode => '0400',
|
||||
content => Sensitive($privatekey),
|
||||
before => Service['puppetserver'],
|
||||
require => File['/var/lib/puppet/keys'],
|
||||
}
|
||||
# manage the eyaml private key
|
||||
file { '/var/lib/puppet/keys/public_key.pkcs7.pem':
|
||||
ensure => 'file',
|
||||
owner => 'puppet',
|
||||
group => 'root',
|
||||
mode => '0400',
|
||||
content => Sensitive($publickey),
|
||||
before => Service['puppetserver'],
|
||||
require => File['/var/lib/puppet/keys'],
|
||||
}
|
||||
}
|
||||
@@ -5,40 +5,12 @@
|
||||
# The latest release of g10k is downloaded from GitHub and placed into '/opt/puppetlabs/bin'.
|
||||
# Additionally, it creates a helper script to easily run g10k with the appropriate configuration.
|
||||
# It also creates a systemd service and timer that runs the g10k script every minute.
|
||||
#
|
||||
# Parameters: None
|
||||
#
|
||||
# Actions:
|
||||
# - Downloads the latest g10k release from GitHub.
|
||||
# - Extracts the download and places the executable in '/opt/puppetlabs/bin'.
|
||||
# - Creates a helper script '/opt/puppetlabs/bin/puppet-g10k' for easy usage of g10k.
|
||||
# - Creates a systemd service and timer that runs the g10k script every minute.
|
||||
#
|
||||
# Usage:
|
||||
# Directly including the class in your node definitions or classify your nodes
|
||||
# using an ENC or Hiera.
|
||||
# Example:
|
||||
# node 'puppet.example.com' {
|
||||
# include profiles::puppet::g10k
|
||||
# }
|
||||
#
|
||||
# Requirements:
|
||||
# - The 'puppet-archive' module should be installed in your puppetmaster.
|
||||
# - The 'puppet-systemd' module should be installed on your puppetmaster.
|
||||
# - '/opt/puppetlabs/bin/' directory must exist and be writable.
|
||||
# - Puppet master must have access to the GitHub URL.
|
||||
#
|
||||
# Limitations:
|
||||
# This is designed to work on Unix-like systems only.
|
||||
class profiles::puppet::g10k (
|
||||
String $bin_path,
|
||||
String $cfg_path,
|
||||
String $environments_path,
|
||||
String $default_environment,
|
||||
){
|
||||
package { 'unzip':
|
||||
ensure => installed,
|
||||
}
|
||||
|
||||
archive { '/tmp/g10k.zip':
|
||||
ensure => present,
|
||||
@@ -47,6 +19,7 @@ class profiles::puppet::g10k (
|
||||
extract_path => '/opt/puppetlabs/bin',
|
||||
creates => '/opt/puppetlabs/bin/g10k',
|
||||
cleanup => true,
|
||||
require => Package['unzip']
|
||||
}
|
||||
|
||||
file { '/opt/puppetlabs/bin/puppet-g10k':
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# profiles::puppet::gems
|
||||
class profiles::puppet::gems (
|
||||
Array $puppet = [],
|
||||
){
|
||||
# install puppetmaster gems
|
||||
$puppet.each | $pgem | {
|
||||
package { $pgem:
|
||||
ensure => installed,
|
||||
provider => 'puppet_gem',
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ class profiles::puppet::puppetboard (
|
||||
Integer $reports_count = 40,
|
||||
Boolean $offline_mode = true,
|
||||
String $default_environment = '*',
|
||||
String $puppetdb_host = lookup('profiles::puppet::puppetdb::puppetdb_host'),
|
||||
String $puppetdb_host = lookup('puppetdbapi'),
|
||||
Stdlib::AbsolutePath $basedir = '/opt/puppetboard',
|
||||
Stdlib::Absolutepath $virtualenv_dir = "${basedir}/venv",
|
||||
Stdlib::Absolutepath $settings_file = "${basedir}/settings.py",
|
||||
@@ -18,8 +18,9 @@ class profiles::puppet::puppetboard (
|
||||
String $gunicorn_bind_prefix = 'http://',
|
||||
Integer $gunicorn_workers = 1,
|
||||
Integer $gunicorn_threads = 4,
|
||||
String $nginx_vhost = 'puppetboard.main.unkin.net',
|
||||
Integer $nginx_port = 80,
|
||||
Stdlib::Port $nginx_port = 80,
|
||||
Stdlib::Host $nginx_vhost = 'puppetboard.main.unkin.net',
|
||||
Array[Stdlib::Host] $nginx_aliases = [],
|
||||
#String[1] $secret_key = "${fqdn_rand_string(32)}",
|
||||
) {
|
||||
|
||||
@@ -98,10 +99,12 @@ class profiles::puppet::puppetboard (
|
||||
# ensure the nginx service is managed
|
||||
class { 'nginx': }
|
||||
|
||||
$nginx_server_names = unique([$nginx_vhost] + $nginx_aliases)
|
||||
|
||||
# create the nginx vhost
|
||||
nginx::resource::server { $nginx_vhost:
|
||||
listen_port => $nginx_port,
|
||||
server_name => [$nginx_vhost],
|
||||
server_name => $nginx_server_names,
|
||||
proxy => "${gunicorn_bind_prefix}${gunicorn_bind}",
|
||||
proxy_set_header => [
|
||||
'Host $http_host',
|
||||
@@ -120,4 +123,39 @@ class profiles::puppet::puppetboard (
|
||||
server => $nginx_vhost,
|
||||
location_alias => "${virtualenv_dir}/lib/python${python_version}/site-packages/puppetboard/static",
|
||||
}
|
||||
|
||||
# export haproxy balancemember
|
||||
profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${nginx_port}}":
|
||||
service => 'be_puppetboard',
|
||||
ports => [$nginx_port],
|
||||
options => [
|
||||
"cookie ${facts['networking']['hostname']}",
|
||||
'check',
|
||||
'inter 2s',
|
||||
'rise 3',
|
||||
'fall 2',
|
||||
]
|
||||
}
|
||||
#@@haproxy::balancermember { "${facts['networking']['fqdn']}_${nginx_port}}":
|
||||
# listening_service => 'be_puppetboard',
|
||||
# ports => [$nginx_port],
|
||||
# server_names => $facts['networking']['hostname'],
|
||||
# ipaddresses => $facts['networking']['ip'],
|
||||
# options => [
|
||||
# "cookie ${facts['networking']['hostname']}",
|
||||
# 'check',
|
||||
# 'inter 2s',
|
||||
# 'rise 3',
|
||||
# 'fall 2',
|
||||
# ]
|
||||
#}
|
||||
|
||||
# if selinux is defined, manage it
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
# call the nginx selinux class
|
||||
class { 'profiles::selinux::nginx':
|
||||
require => Class['Nginx'],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Class: profiles::puppet::puppetca
|
||||
#
|
||||
# This class manages Puppet CA
|
||||
class profiles::puppet::puppetca (
|
||||
Boolean $allow_subject_alt_names = false,
|
||||
Boolean $allow_authorization_extensions = false,
|
||||
Boolean $enable_infra_crl = false,
|
||||
Boolean $is_puppetca = false,
|
||||
) {
|
||||
|
||||
# manage the ca.cfg file
|
||||
file { '/etc/puppetlabs/puppetserver/conf.d/ca.conf':
|
||||
ensure => 'file',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0644',
|
||||
content => template('profiles/puppet/puppet_ca.cfg.erb'),
|
||||
notify => Service['puppetserver'],
|
||||
}
|
||||
|
||||
# manage the crl file
|
||||
if $is_puppetca {
|
||||
# export the puppet crl.pem
|
||||
@@file { '/etc/puppetlabs/puppet/ssl/crl.pem':
|
||||
ensure => file,
|
||||
content => file('/etc/puppetlabs/puppet/ssl/crl.pem'),
|
||||
tag => 'crl_pem_export',
|
||||
}
|
||||
}else{
|
||||
# import the puppet crl.pem
|
||||
File <<| tag == 'crl_pem_export' |>> {
|
||||
require => Service['puppetserver'],
|
||||
}
|
||||
}
|
||||
|
||||
# register the PuppetCA service with consul
|
||||
if $is_puppetca {
|
||||
consul::service { 'puppetca':
|
||||
service_name => 'puppetca',
|
||||
tags => ['ca', 'puppet', 'ssl'],
|
||||
address => $facts['networking']['ip'],
|
||||
port => 8140,
|
||||
checks => [
|
||||
{
|
||||
id => 'puppetca_https_check',
|
||||
name => 'PuppetCA HTTPS Check',
|
||||
http => "https://${facts['networking']['fqdn']}:8140/status/v1/simple",
|
||||
method => 'GET',
|
||||
tls_skip_verify => true,
|
||||
interval => '10s',
|
||||
timeout => '1s',
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,45 @@
|
||||
# configure the puppetdb api service
|
||||
class profiles::puppet::puppetdb_api (
|
||||
String $postgres_host = lookup('profiles::puppet::puppetdb::postgres_host'),
|
||||
String $postgres_host = lookup('puppetdbsql'),
|
||||
String $listen_address = $facts['networking']['ip'],
|
||||
Stdlib::Absolutepath $java_bin = '/usr/bin/java',
|
||||
Hash $java_args = {},
|
||||
) {
|
||||
|
||||
class { 'puppetdb::server':
|
||||
database_host => $postgres_host,
|
||||
manage_firewall => false,
|
||||
ssl_listen_address => $listen_address,
|
||||
listen_address => $listen_address,
|
||||
# wait for enc_role to match the required role
|
||||
if $facts['enc_role'] == 'roles::infra::puppetdb::api' {
|
||||
class { 'java':
|
||||
package => 'java-11-openjdk-devel',
|
||||
before => Class['puppetdb::server'],
|
||||
}
|
||||
|
||||
class { 'puppetdb::server':
|
||||
database_host => $postgres_host,
|
||||
manage_firewall => false,
|
||||
ssl_listen_address => $listen_address,
|
||||
listen_address => $listen_address,
|
||||
java_bin => $java_bin,
|
||||
java_args => $java_args,
|
||||
}
|
||||
|
||||
contain ::puppetdb::server
|
||||
|
||||
class { 'prometheus::puppetdb_exporter':
|
||||
puppetdb_url => "http://${listen_address}:8080/pdb/query",
|
||||
export_scrape_job => true,
|
||||
}
|
||||
|
||||
# export haproxy balancemember
|
||||
profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_8080":
|
||||
service => 'be_puppetdbapi',
|
||||
ports => [8080],
|
||||
options => [
|
||||
"cookie ${facts['networking']['hostname']}",
|
||||
'check',
|
||||
'inter 2s',
|
||||
'rise 3',
|
||||
'fall 2',
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
contain ::puppetdb::server
|
||||
|
||||
class { 'prometheus::puppetdb_exporter':
|
||||
puppetdb_url => "http://${listen_address}:8080/pdb/query",
|
||||
export_scrape_job => true,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# configure the puppetdb sql service
|
||||
class profiles::puppet::puppetdb_sql (
|
||||
String $puppetdb_host = lookup('profiles::puppet::puppetdb::puppetdb_host'),
|
||||
String $puppetdb_host = lookup('puppetdbsql'),
|
||||
String $listen_address = $facts['networking']['ip'],
|
||||
) {
|
||||
|
||||
@@ -24,4 +24,12 @@ class profiles::puppet::puppetdb_sql (
|
||||
|
||||
contain ::puppetdb::database::postgresql
|
||||
|
||||
# create the postgresql::server::config_entry resources
|
||||
$pg_config_entries = lookup('postgresql_config_entries', Hash[String, Data], 'hash', {})
|
||||
$pg_config_entries.each |String $key, Data $value| {
|
||||
postgresql::server::config_entry { $key:
|
||||
ensure => 'present',
|
||||
value => $value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,63 +2,37 @@
|
||||
#
|
||||
# This class manages the puppetmaster using the ghoneycutt-puppet module.
|
||||
# It manages the server settings in the puppet.conf file.
|
||||
#
|
||||
# Parameters: None
|
||||
#
|
||||
# Actions:
|
||||
# - Sets up the server, main, agent, and master sections in the puppet.conf file
|
||||
#
|
||||
# Usage:
|
||||
# Directly include the class in your node definitions or classify your nodes
|
||||
# using an ENC or Hiera.
|
||||
# Example:
|
||||
# node 'puppet.example.com' {
|
||||
# include profiles::puppet::puppetmaster
|
||||
# }
|
||||
#
|
||||
# Requirements:
|
||||
# - The 'ghoneycutt/puppet' module should be installed in your Puppet master.
|
||||
# - Puppet master must have access to the necessary directories.
|
||||
#
|
||||
# Limitations:
|
||||
# This is designed to work on Unix-like systems.
|
||||
class profiles::puppet::puppetmaster (
|
||||
String $puppetdb_host = lookup('profiles::puppet::puppetdb::puppetdb_host'),
|
||||
Optional[Stdlib::Fqdn] $puppetdb_host = lookup('puppetdbapi', Optional[Stdlib::Fqdn], 'first', undef),
|
||||
) {
|
||||
include profiles::puppet::r10k
|
||||
include profiles::puppet::g10k
|
||||
include profiles::puppet::enc
|
||||
include profiles::puppet::autosign
|
||||
|
||||
class { 'puppetdb::master::config':
|
||||
puppetdb_server => $puppetdb_host,
|
||||
manage_storeconfigs => false,
|
||||
if $facts['enc_role'] == 'roles::infra::puppet::master' {
|
||||
|
||||
include profiles::puppet::r10k
|
||||
include profiles::puppet::g10k
|
||||
include profiles::puppet::enc
|
||||
include profiles::puppet::cobbler_enc
|
||||
include profiles::puppet::autosign
|
||||
include profiles::puppet::gems
|
||||
include profiles::helpers::certmanager
|
||||
include profiles::puppet::server
|
||||
include profiles::puppet::puppetca
|
||||
include profiles::puppet::eyaml
|
||||
|
||||
class { 'puppetdb::master::config':
|
||||
puppetdb_server => $puppetdb_host,
|
||||
manage_storeconfigs => false,
|
||||
}
|
||||
|
||||
Package['puppetserver']
|
||||
-> Class['profiles::puppet::gems']
|
||||
-> Class['profiles::puppet::r10k']
|
||||
-> Class['profiles::puppet::g10k']
|
||||
-> Class['profiles::puppet::enc']
|
||||
-> Class['profiles::puppet::cobbler_enc']
|
||||
-> Class['profiles::puppet::autosign']
|
||||
-> Class['puppetdb::master::config']
|
||||
-> Class['profiles::puppet::server']
|
||||
}
|
||||
|
||||
class { 'profiles::puppet::server':
|
||||
vardir => '/opt/puppetlabs/server/data/puppetserver',
|
||||
logdir => '/var/log/puppetlabs/puppetserver',
|
||||
rundir => '/var/run/puppetlabs/puppetserver',
|
||||
pidfile => '/var/run/puppetlabs/puppetserver/puppetserver.pid',
|
||||
codedir => '/etc/puppetlabs/code',
|
||||
dns_alt_names => [
|
||||
'prodinf01n01.main.unkin.net',
|
||||
'puppet.main.unkin.net',
|
||||
'puppetca.main.unkin.net',
|
||||
'puppetmaster.main.unkin.net',
|
||||
'puppet',
|
||||
'puppetca',
|
||||
'puppetmaster',
|
||||
],
|
||||
server => 'prodinf01n01.main.unkin.net',
|
||||
node_terminus => 'exec',
|
||||
external_nodes => '/opt/puppetlabs/bin/enc',
|
||||
autosign => '/etc/puppetlabs/puppet/autosign.conf',
|
||||
default_manifest => '/etc/puppetlabs/code/environments/develop/manifests',
|
||||
default_environment => 'develop',
|
||||
storeconfigs => true,
|
||||
storeconfigs_backend => 'puppetdb',
|
||||
reports => 'puppetdb',
|
||||
usecacheonfailure => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,41 +4,10 @@
|
||||
# systemd service and timer to keep the repository updated every minute.
|
||||
# The Git package is installed if not present, and the repository at the given
|
||||
# location will always reflect the state of the remote Git repository.
|
||||
#
|
||||
# Parameters:
|
||||
# - r10k_repo: The URL of the Git repository to clone.
|
||||
#
|
||||
# Actions:
|
||||
# - Ensures the Git package is installed.
|
||||
# - Ensures the /etc/puppetlabs/r10k directory is a clone of the given Git repository.
|
||||
# - Creates a helper script '/opt/puppetlabs/bin/puppet-r10k' for updating the Git repository.
|
||||
# - Creates a systemd service and timer that runs the git update script every minute.
|
||||
#
|
||||
# Usage:
|
||||
# Directly include the class in your node definitions or classify your nodes
|
||||
# using an enc or Hiera.
|
||||
# Example:
|
||||
# node 'puppet.example.com' {
|
||||
# class { 'profiles::puppet::r10k':
|
||||
# r10k_repo => 'https://github.com/user/repo.git',
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Requirements:
|
||||
# - The 'puppet-vcsrepo' module should be installed on your puppetmaster.
|
||||
# - The 'puppet-systemd' module should be installed on your puppetmaster.
|
||||
# - '/opt/puppetlabs/bin/' directory must exist and be writable.
|
||||
# - Puppet master must have access to the specified Git URL.
|
||||
#
|
||||
# Limitations:
|
||||
# This is designed to work on Unix-like systems only.
|
||||
#
|
||||
class profiles::puppet::r10k (
|
||||
String $r10k_repo,
|
||||
){
|
||||
|
||||
include profiles::packages::git
|
||||
|
||||
vcsrepo { '/etc/puppetlabs/r10k':
|
||||
ensure => latest,
|
||||
provider => git,
|
||||
|
||||
@@ -1,36 +1,33 @@
|
||||
# Class: profiles::puppet::server
|
||||
#
|
||||
# This class manages Puppet server's configuration and service.
|
||||
#
|
||||
# Parameters:
|
||||
# vardir - Directory path for variable data.
|
||||
# logdir - Directory path for logs.
|
||||
# rundir - Directory path for run-time data.
|
||||
# pidfile - File path for the PID file.
|
||||
# codedir - Directory path for code data.
|
||||
# dns_alt_names - Array of alternate DNS names for the server.
|
||||
# server - Server's name.
|
||||
# node_terminus - Node terminus.
|
||||
# external_nodes - Path to the external node classifier script.
|
||||
# autosign - Path to the autosign script.
|
||||
#
|
||||
class profiles::puppet::server (
|
||||
String $vardir,
|
||||
String $logdir,
|
||||
String $rundir,
|
||||
String $pidfile,
|
||||
String $codedir,
|
||||
Array[String[1]] $dns_alt_names,
|
||||
String $server,
|
||||
String $node_terminus,
|
||||
String $external_nodes,
|
||||
String $autosign,
|
||||
String $default_manifest,
|
||||
String $default_environment,
|
||||
Boolean $storeconfigs,
|
||||
String $storeconfigs_backend,
|
||||
String $reports,
|
||||
Boolean $usecacheonfailure,
|
||||
Stdlib::Absolutepath $vardir = '/opt/puppetlabs/server/data/puppetserver',
|
||||
Stdlib::Absolutepath $logdir = '/var/log/puppetlabs/puppetserver',
|
||||
Stdlib::Absolutepath $rundir = '/var/run/puppetlabs/puppetserver',
|
||||
Stdlib::Absolutepath $pidfile = '/var/run/puppetlabs/puppetserver/puppetserver.pid',
|
||||
Stdlib::Absolutepath $codedir = '/etc/puppetlabs/code',
|
||||
Array[String] $dns_alt_names = [
|
||||
$facts['networking']['fqdn'],
|
||||
$facts['networking']['hostname'],
|
||||
],
|
||||
Stdlib::Fqdn $agent_server = 'puppetmaster',
|
||||
Stdlib::Fqdn $report_server = $agent_server,
|
||||
Stdlib::Fqdn $ca_server = 'puppetca',
|
||||
String $node_terminus = 'exec',
|
||||
String $external_nodes = '/opt/cobbler-enc/cobbler-enc',
|
||||
String $default_environment = 'develop',
|
||||
String $environment = 'develop',
|
||||
Stdlib::Absolutepath $autosign = '/etc/puppetlabs/puppet/autosign.conf',
|
||||
Stdlib::Absolutepath $default_manifest = "${codedir}/environments/${default_environment}/manifests",
|
||||
String $reports = 'puppetdb',
|
||||
Boolean $storeconfigs = true,
|
||||
String $storeconfigs_backend = 'puppetdb',
|
||||
Boolean $usecacheonfailure = false,
|
||||
Boolean $report = true,
|
||||
Integer $runinterval = 1800,
|
||||
Integer $runtimeout = 3600,
|
||||
Boolean $show_diff = true,
|
||||
) {
|
||||
|
||||
file { '/etc/puppetlabs/puppet/puppet.conf':
|
||||
@@ -44,8 +41,15 @@ class profiles::puppet::server (
|
||||
'rundir' => $rundir,
|
||||
'pidfile' => $pidfile,
|
||||
'codedir' => $codedir,
|
||||
'dns_alt_names' => join($dns_alt_names, ','),
|
||||
'server' => $server,
|
||||
'dns_alt_names' => join(sort($dns_alt_names), ','),
|
||||
'server' => $agent_server,
|
||||
'ca_server' => $ca_server,
|
||||
'environment' => $environment,
|
||||
'report' => $report,
|
||||
'runinterval' => $runinterval,
|
||||
'runtimeout' => $runtimeout,
|
||||
'show_diff' => $show_diff,
|
||||
'report_server' => $report_server,
|
||||
'node_terminus' => $node_terminus,
|
||||
'external_nodes' => $external_nodes,
|
||||
'autosign' => $autosign,
|
||||
@@ -66,4 +70,3 @@ class profiles::puppet::server (
|
||||
hasrestart => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class profiles::reposync::autosyncer (
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
content => template('profiles/reposync/autosyncer.erb'),
|
||||
require => Class['profiles::packages::reposync'],
|
||||
require => Package['createrepo'],
|
||||
}
|
||||
|
||||
# daily autosyncr service/timer
|
||||
|
||||
@@ -4,7 +4,7 @@ define profiles::reposync::repos (
|
||||
String $description,
|
||||
String $osname,
|
||||
String $release,
|
||||
Stdlib::HTTPUrl $gpgkey,
|
||||
Stdlib::Filesource $gpgkey,
|
||||
String $arch = 'x86_64',
|
||||
String $repo_owner = 'root',
|
||||
String $repo_group = 'root',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# setup a reposync syncer
|
||||
class profiles::reposync::syncer {
|
||||
|
||||
include profiles::packages::reposync
|
||||
include profiles::reposync::autosyncer
|
||||
include profiles::reposync::autopromoter
|
||||
include profiles::reposync::webserver
|
||||
@@ -14,10 +13,13 @@ class profiles::reposync::syncer {
|
||||
mode => '0755',
|
||||
}
|
||||
file { '/etc/reposync/conf.d':
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0755',
|
||||
purge => true,
|
||||
recurse => true,
|
||||
force => true,
|
||||
}
|
||||
|
||||
# get a list of repos as a hash, and iterate through them
|
||||
|
||||
@@ -1,23 +1,120 @@
|
||||
# setup a reposync webserver
|
||||
class profiles::reposync::webserver (
|
||||
String $www_root = '/data/repos/snap',
|
||||
String $cache_root = '/data/repos/cache',
|
||||
String $nginx_vhost = 'repos.main.unkin.net',
|
||||
Integer $nginx_port = 80,
|
||||
Stdlib::Port $nginx_port = 80,
|
||||
Stdlib::Port $nginx_ssl_port = 443,
|
||||
Boolean $favicon = true,
|
||||
Boolean $selinux = true,
|
||||
Enum['http','https','both'] $nginx_listen_mode = 'http',
|
||||
Enum['puppet', 'vault'] $nginx_cert_type = 'vault'
|
||||
) {
|
||||
|
||||
class { 'nginx': }
|
||||
# select the certificates to use based on cert type
|
||||
case $nginx_cert_type {
|
||||
'puppet': {
|
||||
$selected_ssl_cert = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt"
|
||||
$selected_ssl_key = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key"
|
||||
}
|
||||
'vault': {
|
||||
$selected_ssl_cert = '/etc/pki/tls/vault/certificate.crt'
|
||||
$selected_ssl_key = '/etc/pki/tls/vault/private.key'
|
||||
}
|
||||
default: {
|
||||
# enum param prevents this ever being reached
|
||||
}
|
||||
}
|
||||
|
||||
# create the nginx vhost
|
||||
nginx::resource::server { $nginx_vhost:
|
||||
listen_port => $nginx_port,
|
||||
server_name => [$nginx_vhost],
|
||||
use_default_location => true,
|
||||
access_log => "/var/log/nginx/${nginx_vhost}_access.log",
|
||||
error_log => "/var/log/nginx/${nginx_vhost}_error.log",
|
||||
www_root => $www_root,
|
||||
autoindex => 'on',
|
||||
# set variables based on the listen_mode
|
||||
case $nginx_listen_mode {
|
||||
'http': {
|
||||
$enable_ssl = false
|
||||
$ssl_cert = undef
|
||||
$ssl_key = undef
|
||||
$listen_port = $nginx_port
|
||||
$listen_ssl_port = undef
|
||||
$extras_hash = {}
|
||||
}
|
||||
'https': {
|
||||
$enable_ssl = true
|
||||
$ssl_cert = $selected_ssl_cert
|
||||
$ssl_key = $selected_ssl_key
|
||||
$listen_port = $nginx_ssl_port
|
||||
$listen_ssl_port = $nginx_ssl_port
|
||||
$extras_hash = {
|
||||
'subscribe' => [File[$ssl_cert], File[$ssl_key]],
|
||||
}
|
||||
}
|
||||
'both': {
|
||||
$enable_ssl = true
|
||||
$ssl_cert = $selected_ssl_cert
|
||||
$ssl_key = $selected_ssl_key
|
||||
$listen_port = $nginx_port
|
||||
$listen_ssl_port = $nginx_ssl_port
|
||||
$extras_hash = {
|
||||
'subscribe' => [File[$ssl_cert], File[$ssl_key]],
|
||||
}
|
||||
}
|
||||
default: {
|
||||
# enum param prevents this ever being reached
|
||||
}
|
||||
}
|
||||
|
||||
# define the default parameters for the nginx server
|
||||
$defaults = {
|
||||
'listen_port' => $listen_port,
|
||||
'server_name' => [$nginx_vhost],
|
||||
'use_default_location' => true,
|
||||
'access_log' => "/var/log/nginx/${nginx_vhost}_access.log",
|
||||
'error_log' => "/var/log/nginx/${nginx_vhost}_error.log",
|
||||
'www_root' => $www_root,
|
||||
'autoindex' => 'on',
|
||||
'ssl' => $enable_ssl,
|
||||
'ssl_cert' => $ssl_cert,
|
||||
'ssl_key' => $ssl_key,
|
||||
'ssl_port' => $listen_ssl_port,
|
||||
}
|
||||
|
||||
# merge the hashes conditionally
|
||||
$nginx_parameters = merge($defaults, $extras_hash)
|
||||
|
||||
# manage the nginx class
|
||||
class { 'nginx':
|
||||
proxy_cache_path => {
|
||||
"${cache_root}/debian" => 'debian:128m',
|
||||
},
|
||||
proxy_cache_levels => '1:2',
|
||||
proxy_cache_keys_zone => 'debian:128m',
|
||||
proxy_cache_max_size => '30000m',
|
||||
proxy_cache_inactive => '60d',
|
||||
proxy_temp_path => "${cache_root}/tmp",
|
||||
}
|
||||
|
||||
# create the nginx vhost with the merged parameters
|
||||
create_resources('nginx::resource::server', { $nginx_vhost => $nginx_parameters })
|
||||
|
||||
# cache debian packages from upstream
|
||||
nginx::resource::location { "${nginx_vhost}-debian":
|
||||
ensure => present,
|
||||
ssl => true,
|
||||
ssl_only => false,
|
||||
location => '/debian',
|
||||
server => $nginx_vhost,
|
||||
proxy => 'http://mirror.gsl.icu/debian',
|
||||
}
|
||||
|
||||
nginx::resource::location { "${nginx_vhost}-debian_pool":
|
||||
ensure => present,
|
||||
ssl => true,
|
||||
ssl_only => false,
|
||||
location => '/debian/pool',
|
||||
server => $nginx_vhost,
|
||||
proxy => 'http://mirror.gsl.icu/debian/pool',
|
||||
proxy_cache => 'debian',
|
||||
proxy_cache_valid => [
|
||||
'200 302 1440h',
|
||||
'404 1m'
|
||||
],
|
||||
}
|
||||
|
||||
if $favicon {
|
||||
@@ -39,10 +136,7 @@ class profiles::reposync::webserver (
|
||||
order => 10,
|
||||
}
|
||||
|
||||
if $selinux {
|
||||
|
||||
# include packages that are required
|
||||
include profiles::packages::selinux
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
# set httpd_sys_content_t to all files under the www_root
|
||||
selinux::fcontext { $www_root:
|
||||
@@ -51,6 +145,13 @@ class profiles::reposync::webserver (
|
||||
pathspec => "${www_root}(/.*)?",
|
||||
}
|
||||
|
||||
# set httpd_sys_rw_content_t to all files under the cache_root
|
||||
selinux::fcontext { $cache_root:
|
||||
ensure => 'present',
|
||||
seltype => 'httpd_sys_rw_content_t',
|
||||
pathspec => "${cache_root}(/.*)?",
|
||||
}
|
||||
|
||||
# make sure we can connect to port 80
|
||||
selboolean { 'httpd_can_network_connect':
|
||||
persistent => true,
|
||||
@@ -63,5 +164,12 @@ class profiles::reposync::webserver (
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext[$www_root],
|
||||
}
|
||||
|
||||
exec { "restorecon_${cache_root}":
|
||||
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
|
||||
command => "restorecon -Rv ${cache_root}",
|
||||
refreshonly => true,
|
||||
subscribe => Selinux::Fcontext[$cache_root],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ class profiles::selinux::mysqld (
|
||||
Boolean $selinuxuser_mysql_connect_enabled = true,
|
||||
String $selinux_mode = 'enforcing',
|
||||
){
|
||||
# include packages that are required
|
||||
include profiles::packages::selinux
|
||||
|
||||
# setenforce
|
||||
class { 'profiles::selinux::setenforce':
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# profiles::selinux::nginx
|
||||
# selinux settings for nginx
|
||||
class profiles::selinux::nginx (
|
||||
Boolean $persistent = true,
|
||||
Boolean $httpd_can_network_connect = true,
|
||||
String $selinux_mode = 'enforcing',
|
||||
){
|
||||
|
||||
# setenforce
|
||||
class { 'profiles::selinux::setenforce':
|
||||
mode => $selinux_mode,
|
||||
}
|
||||
|
||||
# make sure we can connect to network resources
|
||||
selboolean { 'httpd_can_network_connect':
|
||||
persistent => $persistent,
|
||||
value => $httpd_can_network_connect,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ class profiles::selinux::setenforce (
|
||||
Enum['enforcing', 'permissive', 'disabled'] $mode = 'enforcing',
|
||||
) {
|
||||
class { 'selinux':
|
||||
mode => $mode,
|
||||
mode => $mode,
|
||||
require => Package['policycoreutils']
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ class profiles::sql::galera_member (
|
||||
Boolean $package_manage = true,
|
||||
String $package_name = 'mariadb-server',
|
||||
Boolean $epel_needed = false,
|
||||
Boolean $selinux = true,
|
||||
Boolean $manage_repo = true,
|
||||
) {
|
||||
|
||||
@@ -48,7 +47,7 @@ class profiles::sql::galera_member (
|
||||
}
|
||||
|
||||
# if it is, find hosts, sort them so they dont cause changes every run
|
||||
$servers_array = sort(query_nodes("enc_role='${galera_members_role}'", 'networking.fqdn'))
|
||||
$servers_array = sort(query_nodes("enc_role='${galera_members_role}' and region='${facts['region']}'", 'networking.fqdn'))
|
||||
|
||||
# else use provided array from params
|
||||
}else{
|
||||
@@ -59,10 +58,10 @@ class profiles::sql::galera_member (
|
||||
if length($servers_array) >= 3 {
|
||||
|
||||
# if selinux is defined, manage it
|
||||
if $selinux {
|
||||
if $::facts['os']['selinux']['config_mode'] == 'enforcing' {
|
||||
|
||||
# set permissive on first run, as we need mariadb installed/started at a custom path before adding fcontext
|
||||
if $::facts['mariadb_acti'] { $selinux_mode = 'enforcing' }else{ $selinux_mode = 'permissive' }
|
||||
if $::facts['mariadb_active'] { $selinux_mode = 'enforcing' }else{ $selinux_mode = 'permissive' }
|
||||
|
||||
# call the mysqld selinux class
|
||||
class { 'profiles::selinux::mysqld':
|
||||
@@ -104,7 +103,8 @@ class profiles::sql::galera_member (
|
||||
'binlog_format' => 'ROW',
|
||||
'default-storage-engine' => 'innodb',
|
||||
'query_cache_size' => '0',
|
||||
'query_cache_type' => '0'
|
||||
'query_cache_type' => '0',
|
||||
'bind-address' => $local_ip,
|
||||
}
|
||||
}
|
||||
$default_override_options_galera = {
|
||||
@@ -212,4 +212,5 @@ class profiles::sql::galera_member (
|
||||
}else{
|
||||
notice("${title} requires the servers_array to have 3 or more, currently it is ${length($servers_array)}.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# profiles::storage::datavol
|
||||
#
|
||||
# This define manages the creation of a logical volume using the `lvm::volume` definition.
|
||||
#
|
||||
# Parameters:
|
||||
# $ensure - Ensure whether the logical volume is present or not. Defaults to 'present'.
|
||||
# $vg - Volume group name. No default.
|
||||
# $pv - Physical volume, typically the disk or partition device path. No default.
|
||||
# $fstype - Filesystem type for the logical volume. Defaults to 'ext3'.
|
||||
# $size - Size of the logical volume. undef = 100%FREE. Changing $size to cause a resize.
|
||||
#
|
||||
define profiles::storage::datavol (
|
||||
Enum['present', 'absent'] $ensure = 'present',
|
||||
Enum['ext2', 'ext3', 'ext4', 'xfs', 'btrfs'] $fstype = 'xfs',
|
||||
String $vg = 'datavg',
|
||||
String $pv = '/dev/vdb',
|
||||
String $lv = 'data',
|
||||
String $owner = 'root',
|
||||
String $group = 'root',
|
||||
Stdlib::Filemode $mode = '0755',
|
||||
Stdlib::Absolutepath $mount = '/data',
|
||||
Optional[Variant[Pattern[/^\d+(M|G|T|P)$/], Integer]] $size = undef,
|
||||
Array[Enum[
|
||||
'defaults', 'ro', 'rw', 'sync', 'async',
|
||||
'noatime', 'nodiratime', 'noexec', 'nosuid',
|
||||
'nodev', 'remount', 'auto', 'noauto'
|
||||
]] $mount_options = ['noatime', 'nodiratime'],
|
||||
) {
|
||||
|
||||
# Ensure the physical volume exists
|
||||
physical_volume { $pv:
|
||||
ensure => $ensure,
|
||||
before => Volume_group[$vg],
|
||||
}
|
||||
|
||||
# Ensure the volume group exists
|
||||
volume_group { $vg:
|
||||
ensure => $ensure,
|
||||
physical_volumes => [$pv],
|
||||
before => Logical_volume[$lv],
|
||||
}
|
||||
|
||||
# Ensure the logical volume exists
|
||||
logical_volume { $lv:
|
||||
ensure => $ensure,
|
||||
volume_group => $vg,
|
||||
size => $size,
|
||||
before => Filesystem["/dev/${vg}/${lv}"],
|
||||
}
|
||||
|
||||
# Ensure the filesystem is created on the logical volume
|
||||
filesystem { "/dev/${vg}/${lv}":
|
||||
ensure => $ensure,
|
||||
fs_type => $fstype,
|
||||
require => Logical_volume[$lv],
|
||||
before => Mount[$mount],
|
||||
}
|
||||
|
||||
# Ensure the mountpath exists
|
||||
file { $mount:
|
||||
ensure => directory,
|
||||
owner => $owner,
|
||||
group => $group,
|
||||
mode => $mode,
|
||||
}
|
||||
|
||||
# Ensure the logical volume is mounted at the desired location
|
||||
mount { $mount:
|
||||
ensure => $ensure,
|
||||
device => "/dev/${vg}/${lv}",
|
||||
fstype => $fstype,
|
||||
options => $mount_options.join(','),
|
||||
require => Filesystem["/dev/${vg}/${lv}"],
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user