From 0a978e651d405d58581786c5300d74cb6871ccc1 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sun, 30 Mar 2025 01:03:25 +1100 Subject: [PATCH] feat: add incus module - add a basic incus module --- modules/incus/lib/facter/incus.rb | 18 ++++++ modules/incus/manifests/cluster.pp | 57 +++++++++++++++++++ modules/incus/manifests/init.pp | 35 ++++++++++++ modules/incus/templates/join_preseed.yaml.erb | 20 +++++++ 4 files changed, 130 insertions(+) create mode 100644 modules/incus/lib/facter/incus.rb create mode 100644 modules/incus/manifests/cluster.pp create mode 100644 modules/incus/manifests/init.pp create mode 100644 modules/incus/templates/join_preseed.yaml.erb diff --git a/modules/incus/lib/facter/incus.rb b/modules/incus/lib/facter/incus.rb new file mode 100644 index 0000000..e9639f6 --- /dev/null +++ b/modules/incus/lib/facter/incus.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'yaml' + +Facter.add(:incus) do + setcode do + # Check if the 'incus' executable exists + incus_path = Facter::Util::Resolution.which('incus') + next {} unless incus_path # Return an empty fact if incus isn't found + + # Run the `incus info` command using the found path + incus_output = Facter::Core::Execution.execute("#{incus_path} info") + next {} if incus_output.empty? # Return an empty fact if there's no output + + # Parse the output as YAML and return it + YAML.safe_load(incus_output) + end +end diff --git a/modules/incus/manifests/cluster.pp b/modules/incus/manifests/cluster.pp new file mode 100644 index 0000000..80c76b5 --- /dev/null +++ b/modules/incus/manifests/cluster.pp @@ -0,0 +1,57 @@ +# manage incus clusters +class incus::cluster ( + Boolean $members_lookup = false, + String $members_role = undef, + String $master = undef, + Array $servers = [], + Stdlib::Fqdn $server_fqdn = $facts['networking']['fqdn'], + Stdlib::Port $server_port = 8443, +){ + + # check that the master is named + unless !($master == undef) { + fail("master must be provided for ${title}") + } + + # if lookup is enabled + 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 = $servers + } + + # if its not an empty array. Give puppetdb a chance to be populated with data. + if length($servers_array) >= 3 { + + # check if this is the master_node + if $master == $trusted['certname'] { + $master_bool = true + }else{ + $master_bool = false + } + + # find bootstrap status for servers + $bootstrap_array = puppetdb_query("inventory[certname, facts] { facts.enc_role = '${members_role}' }").map |$node| { + { + 'fqdn' => $node['certname'], + 'ip' => $node['facts']['networking']['ip'], + 'clustered' => $node['facts']['incus']['environment']['server_clustered'], + 'certificate' => $node['facts']['incus']['environment']['certificate'], + } + } + + # determine if the cluster is bootstrapped + $cluster_bootstrapped = $bootstrap_array.any |$server| { + $server['fqdn'] == $master and $server['clustered'] == true + } + } +} diff --git a/modules/incus/manifests/init.pp b/modules/incus/manifests/init.pp new file mode 100644 index 0000000..0e7dc19 --- /dev/null +++ b/modules/incus/manifests/init.pp @@ -0,0 +1,35 @@ +class incus ( + Array[String] $packages = [ + 'incus', + 'incus-tools', + 'incus-client' + ], +) { + + package { $packages: + ensure => installed, + } + + service { 'incus': + ensure => running, + enable => true, + hasstatus => true, + hasrestart => true, + } + + file_line { 'subuid_root': + ensure => present, + path => '/etc/subuid', + line => 'root:1000000:1000000000', + match => '^root:', + notify => Service['incus'], + } + + file_line { 'subgid_root': + ensure => present, + path => '/etc/subgid', + line => 'root:1000000:1000000000', + match => '^root:', + notify => Service['incus'], + } +} diff --git a/modules/incus/templates/join_preseed.yaml.erb b/modules/incus/templates/join_preseed.yaml.erb new file mode 100644 index 0000000..9491b08 --- /dev/null +++ b/modules/incus/templates/join_preseed.yaml.erb @@ -0,0 +1,20 @@ +config: {} +networks: [] +storage_pools: [] +profiles: [] +projects: [] +cluster: + server_name: <%= @server_fqdn %> + enabled: true + member_config: + - entity: storage-pool + name: local + key: source + value: "" + description: '"source" property for storage pool "local"' + cluster_address: <%= @cluster_address %>:<%= @server_port %> + cluster_certificate: | + <%= @certificate %> + server_address: <%= @server_fqdn %>:<%= @server_port %> + cluster_token: <%= @cluster_token %> + cluster_certificate_path: "" -- 2.47.3