Merge pull request 'feat: deploy cobbler enc' (#146) from neoloc/cobbler_enc into develop

Reviewed-on: unkinben/puppet-prod#146
This commit is contained in:
Ben Vincent 2024-04-03 13:05:05 +09:30
commit e69b3a9dc4
5 changed files with 131 additions and 1 deletions

View File

@ -58,6 +58,7 @@ profiles::packages::install:
- pbzip2
- pigz
- pv
- python3.11
- rsync
- screen
- socat

View File

@ -10,6 +10,12 @@ profiles::puppet::autosign::domains:
# profiles::puppet::autosign::nodes:
# - 'somenode.main.unkin.net'
profiles::puppet::cobbler_enc::cobbler_scheme: https
profiles::puppet::cobbler_enc::cobbler_hostname: cobbler.main.unkin.net
profiles::puppet::cobbler_enc::version: 'system'
profiles::puppet::cobbler_enc::packages:
- 'requests'
- 'PyYAML'
profiles::puppet::enc::repo: https://git.unkin.net/unkinben/puppet-enc.git
profiles::puppet::r10k::r10k_repo: https://git.unkin.net/unkinben/puppet-r10k.git
profiles::puppet::g10k::bin_path: '/opt/puppetlabs/bin/g10k'

View File

@ -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}"],
}
}
}

View File

@ -28,6 +28,7 @@ class profiles::puppet::puppetmaster (
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
@ -54,7 +55,7 @@ class profiles::puppet::puppetmaster (
],
server => 'prodinf01n01.main.unkin.net',
node_terminus => 'exec',
external_nodes => '/opt/puppetlabs/bin/enc',
external_nodes => '/opt/cobbler-enc/cobbler-enc',
autosign => '/etc/puppetlabs/puppet/autosign.conf',
default_manifest => '/etc/puppetlabs/code/environments/develop/manifests',
default_environment => 'develop',

View File

@ -0,0 +1,46 @@
#!<%= @venv_path %>/bin/python
"""
External Node Classifier (ENC) for Puppet.
If the environment specified in the YAML file is 'testing',
the environment is not included in the output.
"""
import sys
import yaml
import requests
def fetch_enc_data(cobbler_url: str, hostname: str) -> str:
"""
Fetches and modifies ENC data from a given URL to ensure classes are in list format.
"""
url = f"{cobbler_url}/cblr/svc/op/puppet/hostname/{hostname}"
try:
response = requests.get(url, verify='<%= @trusted_ca_cert %>')
response.raise_for_status()
except requests.RequestException as e:
sys.exit(f"Request failed: {e}")
data = yaml.safe_load(response.text)
data["parameters"] = data.get("parameters", {})
# Ensure 'classes' is in the desired list format
if "classes" in data:
if isinstance(data["classes"], dict):
data["parameters"]["enc_role"] = list(data["classes"].keys())
data["classes"] = list(data["classes"].keys())
else:
data["parameters"]["enc_role"] = list(data["classes"])
data["classes"] = list(data["classes"])
if "environment" in data:
data["parameters"]["enc_env"] = data["environment"]
if data["environment"] == "testing":
del data["environment"]
return yaml.dump(data)
if __name__ == "__main__":
if len(sys.argv) != 2:
sys.exit(f"Usage: {sys.argv[0]} <hostname>")
print(fetch_enc_data("<%= @cobbler_base_url %>", sys.argv[1]))