From 19836e2069dbc2e1712f84483860b5440b7bec92 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Thu, 2 Nov 2023 20:09:22 +1100 Subject: [PATCH] feat: adding reposync wrapper and tooling - add autosyncer/autopromoter scripts - add timer and service to initial sync process - add timer/service for daily/weekly/monthly autopromote - add define to manage each repo - add nginx webserver to share repos - add favion.ico if enabled - add selinux management, and packages for selinux - cleanup package management, sorting package groups into package classes --- Puppetfile | 1 + hieradata/common.yaml | 44 +++++++- site/profiles/files/reposync/favicon.ico | Bin 0 -> 32038 bytes site/profiles/manifests/base.pp | 21 +--- site/profiles/manifests/base/packages.pp | 27 ----- site/profiles/manifests/git/git.pp | 24 ---- site/profiles/manifests/packages/base.pp | 21 ++++ site/profiles/manifests/packages/git.pp | 11 ++ site/profiles/manifests/packages/reposync.pp | 11 ++ site/profiles/manifests/packages/selinux.pp | 11 ++ site/profiles/manifests/puppet/enc.pp | 2 +- site/profiles/manifests/puppet/r10k.pp | 2 +- .../manifests/reposync/autopromoter.pp | 105 ++++++++++++++++++ .../profiles/manifests/reposync/autosyncer.pp | 44 ++++++++ site/profiles/manifests/reposync/repos.pp | 46 ++++++++ site/profiles/manifests/reposync/syncer.pp | 30 +++++ site/profiles/manifests/reposync/webserver.pp | 58 ++++++++++ .../templates/reposync/autopromoter.erb | 53 +++++++++ .../templates/reposync/autosyncer.erb | 97 ++++++++++++++++ .../profiles/templates/reposync/repo_conf.erb | 8 ++ site/roles/manifests/infra/packagerepo.pp | 1 + 21 files changed, 547 insertions(+), 70 deletions(-) create mode 100644 site/profiles/files/reposync/favicon.ico delete mode 100644 site/profiles/manifests/base/packages.pp delete mode 100644 site/profiles/manifests/git/git.pp create mode 100644 site/profiles/manifests/packages/base.pp create mode 100644 site/profiles/manifests/packages/git.pp create mode 100644 site/profiles/manifests/packages/reposync.pp create mode 100644 site/profiles/manifests/packages/selinux.pp create mode 100644 site/profiles/manifests/reposync/autopromoter.pp create mode 100644 site/profiles/manifests/reposync/autosyncer.pp create mode 100644 site/profiles/manifests/reposync/repos.pp create mode 100644 site/profiles/manifests/reposync/syncer.pp create mode 100644 site/profiles/manifests/reposync/webserver.pp create mode 100644 site/profiles/templates/reposync/autopromoter.erb create mode 100644 site/profiles/templates/reposync/autosyncer.erb create mode 100644 site/profiles/templates/reposync/repo_conf.erb diff --git a/Puppetfile b/Puppetfile index 1e7b959..1da664c 100644 --- a/Puppetfile +++ b/Puppetfile @@ -22,6 +22,7 @@ mod 'puppet-archive', '7.0.0' mod 'puppet-chrony', '2.6.0' mod 'puppet-puppetboard', '9.0.0' mod 'puppet-nginx', '5.0.0' +mod 'puppet-selinux', '4.1.0' # other mod 'ghoneycutt-puppet', '3.3.0' diff --git a/hieradata/common.yaml b/hieradata/common.yaml index eb3289a..66e571c 100644 --- a/hieradata/common.yaml +++ b/hieradata/common.yaml @@ -6,7 +6,7 @@ profiles::base::ntp_servers: profiles::base::puppet_servers: - 'prodinf01n01.main.unkin.net' -profiles::base::packages::common: +profiles::packages::base: - ccze - curl - dstat @@ -14,6 +14,7 @@ profiles::base::packages::common: - mtr - ncdu - neovim + - rsync - screen - strace - tmux @@ -56,6 +57,42 @@ puppetdb::master::config::create_puppet_service_resource: false profiles::accounts::sysadmin::sshkeys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZ8SRLlPiDylBpdWR9LpvPg4fDVD+DZst4yRPFwMMhta4mnB1H9XuvZkptDhXywWQ7QIcqa2WbhCen0OQJCtwn3s7EYtacmF5MxmwBYocPoK2AArGuh6NA9rwTdLrPdzhZ+gwe88PAzRLNzjm0ZBR+mA9saMbPJdqpKp0AWeAM8QofRQAWuCzQg9i0Pn1KDMvVDRHCZof4pVlHSTyHNektq4ifovn0zhKC8jD/cYu95mc5ftBbORexpGiQWwQ3HZw1IBe0ZETB1qPIPwsoJpt3suvMrL6T2//fcIIUE3TcyJKb/yhztja4TZs5jT8370G/vhlT70He0YPxqHub8ZfBv0khlkY93VBWYpNGJwM1fVqlw7XbfBNdOuJivJac8eW317ZdiDnKkBTxapThpPG3et9ib1HoPGKRsd/fICzNz16h2R3tddSdihTFL+bmTCa6Lo+5t5uRuFjQvhSLSgO2/gRAprc3scYOB4pY/lxOFfq3pU2VvSJtRgLNEYMUYKk= ben@unkin.net +profiles::reposync::repos_list: + almalinux_8_8_baseos: + repository: 'BaseOS' + description: 'AlmaLinux 8.8 - BaseOS' + osname: 'almalinux' + release: '8.8' + baseurl: 'http://mirror.aarnet.edu.au/pub/almalinux/8.8/BaseOS/x86_64/os/' + gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' + almalinux_8_8_appstream: + repository: 'AppStream' + description: 'AlmaLinux 8.8 - AppStream' + osname: 'almalinux' + release: '8.8' + baseurl: 'http://mirror.aarnet.edu.au/pub/almalinux/8.8/AppStream/x86_64/os/' + gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' + almalinux_8_8_highavailability: + repository: 'HighAvailability' + description: 'AlmaLinux 8.8 - HighAvailability' + osname: 'almalinux' + release: '8.8' + baseurl: 'http://mirror.aarnet.edu.au/pub/almalinux/8.8/HighAvailability/x86_64/os/' + gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' + epel_8_everything: + repository: 'Everything' + description: 'EPEL 8 Everything' + osname: 'epel' + release: '8' + baseurl: 'https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/' + gpgkey: 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8' + epel_8_modular: + repository: 'Modular' + description: 'EPEL 8 Modular' + osname: 'epel' + release: '8' + baseurl: 'https://dl.fedoraproject.org/pub/epel/8/Modular/x86_64/' + gpgkey: 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8' profiles::base::hosts::additional_hosts: - ip: 198.18.17.3 @@ -78,3 +115,8 @@ profiles::base::hosts::additional_hosts: hostname: prodinf01n06.main.unkin.net aliases: - prodinf01n06 + - ip: 198.18.17.22 + hostname: prodinf01n22.main.unkin.net + aliases: + - prodinf01n22 + - repo.main.unkin.net diff --git a/site/profiles/files/reposync/favicon.ico b/site/profiles/files/reposync/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6c351da869acfccd096f138b8160e34c5b598f6f GIT binary patch literal 32038 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 ZAbt`&$d+iV$g9Nn@GQ!z2-9f&{U5<0A2I*{ literal 0 HcmV?d00001 diff --git a/site/profiles/manifests/base.pp b/site/profiles/manifests/base.pp index e1a98c0..692ad57 100644 --- a/site/profiles/manifests/base.pp +++ b/site/profiles/manifests/base.pp @@ -19,22 +19,18 @@ class profiles::base ( } } - # include the base packages profile - class { 'profiles::base::packages': - packages => hiera('profiles::base::packages::common'), - ensure => 'installed', - } - # manage puppet clients if ! member($puppet_servers, $trusted['certname']) { include profiles::puppet::client } - # include admin scripts + # include the base profiles + include profiles::packages::base + include profiles::base::facts + include profiles::base::motd include profiles::base::scripts - - # include admin scripts include profiles::base::hosts + include profiles::accounts::sysadmin # include the python class class { 'python': @@ -49,11 +45,4 @@ class profiles::base ( secure_path => '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/opt/puppetlabs/bin' } - # default users - include profiles::accounts::sysadmin - - # add a motd - include profiles::base::facts - include profiles::base::motd - } diff --git a/site/profiles/manifests/base/packages.pp b/site/profiles/manifests/base/packages.pp deleted file mode 100644 index 6c15811..0000000 --- a/site/profiles/manifests/base/packages.pp +++ /dev/null @@ -1,27 +0,0 @@ -# This class manages the installation of packages for the base profile -# -# Parameters: -# - $packages: An array of package names to be installed (optional) -# -# Description: -# This class installs a list of packages specified in the $packages parameter -# using the `package` resource from Puppet. Each package in the array is installed -# with the `ensure => installed` attribute, ensuring that the package is present -# on the target system. By default, the class retrieves the package list from Hiera -# using the key 'profiles::base::packages::common'. -# -# Example usage: -# class { 'profiles::base::packages': -# packages => ['package1', 'package2', 'package3'], -# -class profiles::base::packages ( - Array $packages, - Enum[ - 'present', - 'absent', - 'latest', - 'installed' - ] $ensure = 'installed', -){ - ensure_packages($packages, {'ensure' => $ensure}) -} diff --git a/site/profiles/manifests/git/git.pp b/site/profiles/manifests/git/git.pp deleted file mode 100644 index ca3b4e7..0000000 --- a/site/profiles/manifests/git/git.pp +++ /dev/null @@ -1,24 +0,0 @@ -# Class: profiles::git::git -# -# This class ensures that the Git package is installed. -# -# It uses the 'package' resource to manage the Git package, -# and will ensure that it is installed. This class does not -# manage any configurations related to Git, it only ensures -# that the package is installed. -# -# The class does not take any parameters. -# -# Example usage: -# -------------- -# To use this class, you simply need to declare it in your manifest: -# -# include profiles::git::git -# -# You do not need to pass any parameters. -# -class profiles::git::git { - package { 'git': - ensure => installed, - } -} diff --git a/site/profiles/manifests/packages/base.pp b/site/profiles/manifests/packages/base.pp new file mode 100644 index 0000000..807c8a8 --- /dev/null +++ b/site/profiles/manifests/packages/base.pp @@ -0,0 +1,21 @@ +# This class manages the installation of packages for the base profile +# +# Parameters: +# - $packages: An array of package names to be installed (optional) +# - $ensure: Enum of present, absent, latest or installed (optional) +# +# Example usage: +# class { 'profiles::base::packages': +# packages => ['package1', 'package2', 'package3'], +# +class profiles::packages::base ( + Array $packages = lookup('profiles::packages::base', Array, 'first', []), + Enum[ + 'present', + 'absent', + 'latest', + 'installed' + ] $ensure = 'installed', +){ + ensure_packages($packages, {'ensure' => $ensure}) +} diff --git a/site/profiles/manifests/packages/git.pp b/site/profiles/manifests/packages/git.pp new file mode 100644 index 0000000..578aca7 --- /dev/null +++ b/site/profiles/manifests/packages/git.pp @@ -0,0 +1,11 @@ +# 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, + } + } +} diff --git a/site/profiles/manifests/packages/reposync.pp b/site/profiles/manifests/packages/reposync.pp new file mode 100644 index 0000000..f6525a5 --- /dev/null +++ b/site/profiles/manifests/packages/reposync.pp @@ -0,0 +1,11 @@ +# 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, + } + } +} diff --git a/site/profiles/manifests/packages/selinux.pp b/site/profiles/manifests/packages/selinux.pp new file mode 100644 index 0000000..1bbd457 --- /dev/null +++ b/site/profiles/manifests/packages/selinux.pp @@ -0,0 +1,11 @@ +# 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, + } + } +} diff --git a/site/profiles/manifests/puppet/enc.pp b/site/profiles/manifests/puppet/enc.pp index 4e84227..dad9d11 100644 --- a/site/profiles/manifests/puppet/enc.pp +++ b/site/profiles/manifests/puppet/enc.pp @@ -39,7 +39,7 @@ class profiles::puppet::enc ( Boolean $force = false, ) { - include profiles::git::git + include profiles::packages::git vcsrepo { '/opt/puppetlabs/enc': ensure => latest, diff --git a/site/profiles/manifests/puppet/r10k.pp b/site/profiles/manifests/puppet/r10k.pp index 29d302f..402f49a 100644 --- a/site/profiles/manifests/puppet/r10k.pp +++ b/site/profiles/manifests/puppet/r10k.pp @@ -37,7 +37,7 @@ class profiles::puppet::r10k ( String $r10k_repo, ){ - include profiles::git::git + include profiles::packages::git vcsrepo { '/etc/puppetlabs/r10k': ensure => latest, diff --git a/site/profiles/manifests/reposync/autopromoter.pp b/site/profiles/manifests/reposync/autopromoter.pp new file mode 100644 index 0000000..63c2ab7 --- /dev/null +++ b/site/profiles/manifests/reposync/autopromoter.pp @@ -0,0 +1,105 @@ +# setup the autopromoter +class profiles::reposync::autopromoter { + + # Ensure the autopromoter script is present and executable + file { '/usr/local/bin/autopromoter': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0755', + content => template('profiles/reposync/autopromoter.erb'), + } + + # daily autopromote service/timer + $_daily_timer = @(EOT) + [Unit] + Description=autopromoter daily timer + [Timer] + OnCalendar=*-*-* 05:00:00 + RandomizedDelaySec=1s + [Install] + WantedBy=timers.target + EOT + + $_daily_service = @(EOT) + [Unit] + Description=autopromoter daily service + [Service] + Type=oneshot + ExecStart=/usr/local/bin/autopromoter daily + User=root + Group=root + PermissionsStartOnly=false + PrivateTmp=no + EOT + + systemd::timer { 'autopromoter-daily.timer': + timer_content => $_daily_timer, + service_content => $_daily_service, + active => true, + enable => true, + require => File['/usr/local/bin/autopromoter'], + } + + # weekly autopromote service/timer + $_weekly_timer = @(EOT) + [Unit] + Description=autopromoter weekly timer + [Timer] + OnCalendar=Sun *-*-* 05:05:00 + RandomizedDelaySec=1s + [Install] + WantedBy=timers.target + EOT + + $_weekly_service = @(EOT) + [Unit] + Description=autopromoter weekly service + [Service] + Type=oneshot + ExecStart=/usr/local/bin/autopromoter weekly + User=root + Group=root + PermissionsStartOnly=false + PrivateTmp=no + EOT + + systemd::timer { 'autopromoter-weekly.timer': + timer_content => $_weekly_timer, + service_content => $_weekly_service, + active => true, + enable => true, + require => File['/usr/local/bin/autopromoter'], + } + + # monthly autopromote service/timer + $_monthly_timer = @(EOT) + [Unit] + Description=autopromoter monthly timer + [Timer] + OnCalendar=*-*-01 05:10:00 + RandomizedDelaySec=1s + [Install] + WantedBy=timers.target + EOT + + $_monthly_service = @(EOT) + [Unit] + Description=autopromoter monthly service + [Service] + Type=oneshot + ExecStart=/usr/local/bin/autopromoter monthly + User=root + Group=root + PermissionsStartOnly=false + PrivateTmp=no + EOT + + systemd::timer { 'autopromoter-monthly.timer': + timer_content => $_monthly_timer, + service_content => $_monthly_service, + active => true, + enable => true, + require => File['/usr/local/bin/autopromoter'], + } +} diff --git a/site/profiles/manifests/reposync/autosyncer.pp b/site/profiles/manifests/reposync/autosyncer.pp new file mode 100644 index 0000000..e2e8683 --- /dev/null +++ b/site/profiles/manifests/reposync/autosyncer.pp @@ -0,0 +1,44 @@ +# setup the autosyncer +class profiles::reposync::autosyncer { + + # Ensure the autosyncer script is present and executable + file { '/usr/local/bin/autosyncer': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0755', + content => template('profiles/reposync/autosyncer.erb'), + require => Class['profiles::packages::reposync'], + } + + # daily autosyncr service/timer + $_timer = @(EOT) + [Unit] + Description=autosyncer timer + [Timer] + OnCalendar=*-*-* 03:00:00 + RandomizedDelaySec=1s + [Install] + WantedBy=timers.target + EOT + + $_service = @(EOT) + [Unit] + Description=autosyncer service + [Service] + Type=oneshot + ExecStart=/usr/local/bin/autosyncer + User=root + Group=root + PermissionsStartOnly=false + PrivateTmp=no + EOT + + systemd::timer { 'autosyncer.timer': + timer_content => $_timer, + service_content => $_service, + active => true, + enable => true, + require => File['/usr/local/bin/autosyncer'], + } +} diff --git a/site/profiles/manifests/reposync/repos.pp b/site/profiles/manifests/reposync/repos.pp new file mode 100644 index 0000000..5886785 --- /dev/null +++ b/site/profiles/manifests/reposync/repos.pp @@ -0,0 +1,46 @@ +# define to generate repositories in yum +define profiles::reposync::repos ( + String $repository, + String $description, + String $osname, + String $release, + Stdlib::HTTPUrl $baseurl, + Stdlib::HTTPUrl $gpgkey, + String $arch = 'x86_64', + String $repo_owner = 'root', + String $repo_group = 'root', + Stdlib::Absolutepath $basepath = '/data/repos', +){ + + $repos_name = downcase("${osname}-${release}-${repository}-${arch}") + $conf_file = "/etc/reposync/conf.d/${repos_name}.conf" + + # Create the repository configuration + yumrepo { $repos_name: + ensure => 'present', + descr => $description, + baseurl => $baseurl, + gpgkey => $gpgkey, + target => '/etc/yum.repos.d/reposync.repo', + enabled => 0, + gpgcheck => 1, + } + + # Ensure the repo dest path exists + file { "${basepath}/live/${repos_name}" : + ensure => 'directory', + owner => $repo_owner, + group => $repo_group, + mode => '0755', + } + + # Create the repo configuration file + file { $conf_file: + ensure => file, + owner => $repo_owner, + group => $repo_group, + mode => '0644', + content => template('profiles/reposync/repo_conf.erb'), + require => File['/etc/reposync/conf.d'], + } +} diff --git a/site/profiles/manifests/reposync/syncer.pp b/site/profiles/manifests/reposync/syncer.pp new file mode 100644 index 0000000..6f20996 --- /dev/null +++ b/site/profiles/manifests/reposync/syncer.pp @@ -0,0 +1,30 @@ +# setup a reposync syncer +class profiles::reposync::syncer { + + include profiles::packages::reposync + include profiles::reposync::autosyncer + include profiles::reposync::autopromoter + include profiles::reposync::webserver + + # Ensure the reposync config path exists + file { '/etc/reposync': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + file { '/etc/reposync/conf.d': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + + # get a list of repos as a hash, and iterate through them + $repos = lookup('profiles::reposync::repos_list', {}) + $repos.each | String $name, Hash $repo_hash | { + profiles::reposync::repos { $name: + * => $repo_hash, + } + } +} diff --git a/site/profiles/manifests/reposync/webserver.pp b/site/profiles/manifests/reposync/webserver.pp new file mode 100644 index 0000000..66f549a --- /dev/null +++ b/site/profiles/manifests/reposync/webserver.pp @@ -0,0 +1,58 @@ +# setup a reposync webserver +class profiles::reposync::webserver ( + String $www_root = '/data/repos/snap', + String $nginx_vhost = 'repos.main.unkin.net', + Integer $nginx_port = 80, + Boolean $favicon = true, + Boolean $selinux = true, +) { + + class { 'nginx': } + + # 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', + } + + if $favicon { + file { "${www_root}/favicon.ico": + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + source => 'puppet:///modules/profiles/reposync/favicon.ico', + } + } + + if $selinux { + + # include packages that are required + include profiles::packages::selinux + + # set httpd_sys_content_t to all files under the www_root + selinux::fcontext { $www_root: + ensure => 'present', + seltype => 'httpd_sys_content_t', + pathspec => "${www_root}(/.*)?", + } + + # make sure we can connect to port 80 + selboolean { 'httpd_can_network_connect': + persistent => true, + value => 'on', + } + + exec { "restorecon_${www_root}": + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => "restorecon -Rv ${www_root}", + refreshonly => true, + subscribe => Selinux::Fcontext[$www_root], + } + } +} diff --git a/site/profiles/templates/reposync/autopromoter.erb b/site/profiles/templates/reposync/autopromoter.erb new file mode 100644 index 0000000..0bf995f --- /dev/null +++ b/site/profiles/templates/reposync/autopromoter.erb @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# Function to create symlink for snapshots +create_symlink() { + local osname="$1" + local release="$2" + local repository="$3" + local basepath="$4" + local label="$5" # 'monthly', 'weekly', or 'daily' + local date_format="$6" # Date format for finding the snapshot + + # The path where snapshots are stored + local snap_path="${basepath}/snap/${osname}/${release}/${repository}-${date_format}" + + # The target path for the symlink + local symlink_target="${basepath}/snap/${osname}/${release}/${repository}-${label}" + + # Check if the source directory exists + if [[ -d "$snap_path" ]]; then + # Create the symlink, overwrite if it already exists + ln -sfn "$snap_path" "$symlink_target" + echo "Symlink created for $snap_path -> $symlink_target" + else + echo "Snapshot path does not exist: $snap_path" + return 1 + fi +} + +# Determine which snapshot to promote based on the passed argument +case "$1" in + monthly) + promote_date=$(date --date="$(date +%Y%m01) -1 month" +%Y%m%d) + ;; + weekly) + promote_date=$(date --date="last Sunday" +%Y%m%d) + ;; + daily) + promote_date=$(date --date="yesterday" +%Y%m%d) + ;; + *) + echo "Usage: $0 {monthly|weekly|daily}" + exit 1 + ;; +esac + +# Call the function with appropriate arguments +# Iterate over the repositories to create symlinks for each +for conf in /etc/reposync/conf.d/*.conf; do + source "$conf" + + # Create symlink based on the provided argument + create_symlink "$OSNAME" "$RELEASE" "$REPOSITORY" "$BASEPATH" "$1" "$promote_date" +done diff --git a/site/profiles/templates/reposync/autosyncer.erb b/site/profiles/templates/reposync/autosyncer.erb new file mode 100644 index 0000000..a66ed5d --- /dev/null +++ b/site/profiles/templates/reposync/autosyncer.erb @@ -0,0 +1,97 @@ +#!/usr/bin/bash + +# Function to perform reposync +perform_reposync() { + local reponame="$1" + local basepath="$2" + + /usr/bin/dnf reposync \ + --gpgcheck \ + --delete \ + --downloadcomps \ + --download-metadata \ + --remote-time \ + --disablerepo="*" \ + --enablerepo="${reponame}" \ + --download-path="${basepath}/live" +} + +# Function to download GPG keys +download_gpg_key() { + local gpgkeyurl="$1" + local reponame="$2" + local basepath="$3" + + # Extract filename from URL + local filename=$(basename "$gpgkeyurl") + + # Download GPG key to the specified path with the filename from the URL + wget -q -O "${basepath}/live/${reponame}/${filename}" "$gpgkeyurl" || { + echo "Failed to download GPG key from $gpgkeyurl" + } +} + +# Function to perform rsync with hard links +perform_rsync() { + local source_path="$1" + local dest_path="$2" + + # Create the destination directory if it doesn't exist + mkdir -p "$dest_path" + + # Use rsync to create hard links to the files in the destination directory + rsync -a --link-dest="$source_path" "$source_path"/* "$dest_path" +} + +create_repo_metadata() { + local basepath="${1}" + local osname="${2}" + local release="${3}" + local repository="${4}" + local current_date="${5}" + + local repo_path="${basepath}/snap/${osname}/${release}/${repository}-${current_date}" + + if [[ -d "$repo_path" ]]; then + echo "Running createrepo on ${repo_path}..." + createrepo --update "${repo_path}" + if [[ $? -eq 0 ]]; then + echo "Successfully created repository metadata for ${repository}" + else + echo "Failed to create repository metadata for ${repository}" >&2 + return 1 + fi + else + echo "The specified repository path does not exist: ${repo_path}" >&2 + return 1 + fi +} + +# Current date in the required format +DATE=$(date +%Y%m%d) + +# iterate over each configuration file +for conf in /etc/reposync/conf.d/*.conf; do + + # source the configuration to get the variables + source "$conf" + + # Call the function to download the GPG key + download_gpg_key "$GPGKEYURL" "$REPONAME" "$BASEPATH" + + # Call the reposync function + perform_reposync "$REPONAME" "$BASEPATH" + + # Path for rsync source + live_path="${BASEPATH}/live/${REPONAME}" + + # Path for rsync destination + snap_path="${BASEPATH}/snap/${OSNAME}/${RELEASE}/${REPOSITORY}-${DATE}/${ARCH}/os" + + # Call the rsync function + perform_rsync "$live_path" "$snap_path" + + # After syncing each repo, fix the repository metadata + create_repo_metadata "${BASEPATH}" "${OSNAME}" "${RELEASE}" "${REPOSITORY}" "${DATE}" + +done diff --git a/site/profiles/templates/reposync/repo_conf.erb b/site/profiles/templates/reposync/repo_conf.erb new file mode 100644 index 0000000..99eb2b0 --- /dev/null +++ b/site/profiles/templates/reposync/repo_conf.erb @@ -0,0 +1,8 @@ +# <%= @osname %>-<%= @release %>-<%= @repository %> repository configuration +REPOSITORY="<%= @repository %>" +REPONAME="<%= @repos_name %>" +OSNAME="<%= @osname %>" +RELEASE="<%= @release %>" +ARCH="<%= @arch %>" +BASEPATH="<%= @basepath %>" +GPGKEYURL="<%= @gpgkey %>" diff --git a/site/roles/manifests/infra/packagerepo.pp b/site/roles/manifests/infra/packagerepo.pp index 1f2afdc..ff90820 100644 --- a/site/roles/manifests/infra/packagerepo.pp +++ b/site/roles/manifests/infra/packagerepo.pp @@ -3,4 +3,5 @@ class roles::infra::packagerepo { include profiles::defaults include profiles::base include profiles::base::datavol + include profiles::reposync::syncer }