feat: change enc_* fact to read direct from cobbler (#219)

- change enc_role and enc_env to read direct from cobbler
- cleanup profiles::base::facts

Reviewed-on: https://git.query.consul/unkinben/puppet-prod/pulls/219
This commit is contained in:
Ben Vincent 2025-03-12 23:09:15 +11:00
parent b981a6fb01
commit 8eb751e22f
10 changed files with 80 additions and 73 deletions

View File

@ -3,3 +3,8 @@
detectors:
FeatureEnvy:
enabled: false
TooManyStatements:
enabled: false
UncommunicativeVariableName:
accept:
- e

View File

@ -0,0 +1,74 @@
# frozen_string_literal: true
require 'facter'
require 'yaml'
require 'net/http'
require 'uri'
require 'fileutils'
# CobblerENC module: Fetches ENC data from Cobbler, caches it, and provides structured facts.
module CobblerENC
CACHE_FILE = '/var/cache/puppet_enc.yaml'
CACHE_TTL = 7 * 24 * 60 * 60 # 7 days in seconds
@enc_data = nil # In-memory cache for the ENC response
def self.read_cache
return {} unless File.exist?(CACHE_FILE)
cache_data = YAML.safe_load(File.read(CACHE_FILE)) || {}
timestamp = cache_data.fetch('timestamp', 0)
return cache_data if Time.now.to_i - timestamp < CACHE_TTL
{}
end
def self.write_cache(enc_data)
FileUtils.mkdir_p(File.dirname(CACHE_FILE))
cache_data = enc_data.merge({ 'timestamp' => Time.now.to_i })
File.write(CACHE_FILE, cache_data.to_yaml)
end
def self.fetch_from_cobbler
uri = URI("http://cobbler.main.unkin.net/cblr/svc/op/puppet/hostname/#{Facter.value(:fqdn) || Facter.value(:hostname)}")
response = Net::HTTP.get_response(uri)
raise "Failed to fetch ENC data. HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
YAML.safe_load(response.body) || {}
end
def self.retrieve_enc_data
return @enc_data if @enc_data
@enc_data = fetch_from_cobbler
write_cache(@enc_data)
@enc_data
end
def self.fetch_enc_data
retrieve_enc_data
rescue StandardError => e
Facter.warn("Error retrieving Cobbler ENC data: #{e.message}")
@enc_data = read_cache
return @enc_data unless @enc_data.empty?
raise 'No cached ENC data available and Cobbler is down.'
end
def self.enc_role
fetch_enc_data.fetch('classes', {}).keys.first || raise('ENC Role not found in Cobbler ENC response')
end
def self.enc_env
fetch_enc_data.fetch('environment', nil) || raise('ENC Environment not found in Cobbler ENC response')
end
end
Facter.add('enc_role') do
setcode { CobblerENC.enc_role }
end
Facter.add('enc_env') do
setcode { CobblerENC.enc_env }
end

View File

@ -1,13 +0,0 @@
# frozen_string_literal: true
Facter.add('enc_env') do
setcode do
require 'yaml'
# Check if the YAML file exists
if File.exist?('/root/.cache/custom_facts.yaml')
data = YAML.load_file('/root/.cache/custom_facts.yaml')
# Use safe navigation to return 'enc_env' or nil
data&.dig('enc_env')
end
end
end

View File

@ -1,13 +0,0 @@
# frozen_string_literal: true
Facter.add('enc_role') do
setcode do
require 'yaml'
# Check if the YAML file exists
if File.exist?('/root/.cache/custom_facts.yaml')
data = YAML.load_file('/root/.cache/custom_facts.yaml')
# Use safe navigation to return 'enc_role' or nil
data&.dig('enc_role')
end
end
end

View File

@ -22,7 +22,6 @@ class profiles::base (
# 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

View File

@ -1,39 +0,0 @@
# a class to define some global facts
class profiles::base::facts {
# The path where external facts are stored
$facts_d_path = '/opt/puppetlabs/facter/facts.d'
# Ensure the directory exists
file { $facts_d_path:
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
# cleanup old facts files
$fact_list = [ 'enc_role', 'enc_env' ]
$fact_list.each | String $item | {
file { "${facts_d_path}/${item}.txt":
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'),
}
}

View File

@ -8,8 +8,7 @@ class profiles::firstrun::init {
include profiles::base::repos
include profiles::firstrun::packages
# set the motd and base facts
include profiles::base::facts
# set the motd
include profiles::base::motd
# create the sysadmin account

View File

@ -1,3 +0,0 @@
---
enc_role: <%= @enc_role[0] %>
enc_env: <%= @enc_env %>

View File

@ -1 +0,0 @@
enc_env=<%= @enc_env %>

View File

@ -1 +0,0 @@
enc_role=<%= @enc_role[0] %>