From 0ca4ae08431f19a7a6b25b85f59e187d7ab1a198 Mon Sep 17 00:00:00 2001 From: Joris29 Date: Tue, 16 Jan 2024 08:19:49 +0100 Subject: [PATCH 1/5] Add cli class, project define and type --- data/Debian.yaml | 2 + data/RedHat.yaml | 2 + files/rd_project_diff.sh | 15 ++++ manifests/cli.pp | 125 ++++++++++++++++++++++++++ manifests/config/project.pp | 63 +++++++++++++ spec/classes/cli_spec.rb | 133 ++++++++++++++++++++++++++++ spec/defines/config/project_spec.rb | 68 ++++++++++++++ types/project.pp | 5 ++ 8 files changed, 413 insertions(+) create mode 100644 files/rd_project_diff.sh create mode 100644 manifests/cli.pp create mode 100644 manifests/config/project.pp create mode 100644 spec/classes/cli_spec.rb create mode 100644 spec/defines/config/project_spec.rb create mode 100644 types/project.pp diff --git a/data/Debian.yaml b/data/Debian.yaml index fd73dacf5..61e201441 100644 --- a/data/Debian.yaml +++ b/data/Debian.yaml @@ -74,3 +74,5 @@ rundeck::repo_config: R/VlCBb26ePKjXxliSmEdA== =5ilI -----END PGP PUBLIC KEY BLOCK----- + +rundeck::cli::repo_config: "%{alias('rundeck::repo_config')}" diff --git a/data/RedHat.yaml b/data/RedHat.yaml index ffc954725..e352544db 100644 --- a/data/RedHat.yaml +++ b/data/RedHat.yaml @@ -8,3 +8,5 @@ rundeck::repo_config: gpgcheck: 0 enabled: 1 gpgkey: https://packages.rundeck.com/pagerduty/rundeck/gpgkey + +rundeck::cli::repo_config: "%{alias('rundeck::repo_config')}" diff --git a/files/rd_project_diff.sh b/files/rd_project_diff.sh new file mode 100644 index 000000000..d64c8d602 --- /dev/null +++ b/files/rd_project_diff.sh @@ -0,0 +1,15 @@ +#!/usr/bin/bash + +project="$1" +update_method="$2" +config="$3" +keys="$4" + +if [[ $update_method == 'update' ]] +then + query="jq -S 'with_entries(select(.key as \$k | \"$keys\" | index(\$k)))'" +else + query='jq -S' +fi + +bash -c "diff <(rd projects configure get -p '$project' | $query) <(echo '$config' | jq -S)" diff --git a/manifests/cli.pp b/manifests/cli.pp new file mode 100644 index 000000000..c44a05889 --- /dev/null +++ b/manifests/cli.pp @@ -0,0 +1,125 @@ +# @summary Class to manage installation and configuration of Rundeck CLI. +# +# @example Use cli with token and project config. +# class { 'rundeck::cli': +# manage_repo => false, +# url => 'https://rundeck01.example.com', +# bypass_url => 'https://rundeck.example.com', +# token => 'very_secure', +# projects => { +# 'MyProject' => { +# 'update_method' => 'set', +# 'config' => { +# 'project.description' => 'This is My rundeck project', +# 'project.disable.executions' => 'false', +# }, +# }, +# 'TestProject' => { +# 'config' => { +# 'project.description' => 'This is a rundeck test project', +# 'project.disable.schedule' => 'false', +# }, +# }, +# }, +# } +# +# @param repo_config +# A hash of repository attributes for configuring the rundeck cli package repositories. +# Examples/defaults for yumrepo can be found at RedHat.yaml, and for apt at Debian.yaml +# @param manage_repo +# Whether to manage the cli package repository. +# @param version +# Ensure the state of the rundeck cli package, either present, absent or a specific version. +# @param url +# Rundeck instance/api url. +# @param bypass_url +# Rundeck external url to bypass. This will rewrite any redirect to $bypass_url as $url +# @param user +# Cli user to authenticate. +# @param password +# Cli password to authenticate. +# @param token +# Cli token to authenticate. +# @param projects +# Cli projects config. See example for structure and rundeck::config::project for available params. +# +class rundeck::cli ( + Hash $repo_config, + Boolean $manage_repo = true, + String[1] $version = 'installed', + Stdlib::HTTPUrl $url = 'http://localhost:4440', + Stdlib::HTTPUrl $bypass_url = 'http://localhost:4440', + String[1] $user = 'admin', + String[1] $password = 'admin', + Optional[String[8]] $token = undef, + Hash[String, Rundeck::Project] $projects = {}, +) { + ensure_resource('package', 'jq', { 'ensure' => 'present' }) + + case $facts['os']['family'] { + 'RedHat': { + if $manage_repo { + $repo_config.each | String $_repo_name, Hash $_attributes| { + yumrepo { $_repo_name: + * => $_attributes, + before => Package['rundeck-cli'], + } + } + } + } + 'Debian': { + if $manage_repo { + $repo_config.each | String $_repo_name, Hash $_attributes| { + apt::source { $_repo_name: + * => $_attributes, + before => Package['rundeck-cli'], + } + } + } + + Class['Apt::Update'] -> Package['rundeck-cli'] + } + default: { + err("The osfamily: ${facts['os']['family']} is not supported") + } + } + + package { 'rundeck-cli': + ensure => $version, + } + + file { '/usr/local/bin/rd_project_diff.sh': + ensure => file, + content => file('rundeck/rd_project_diff.sh'), + mode => '0755', + } + + $_default_env_vars = [ + 'RD_FORMAT=json', + "RD_URL=${url}", + "RD_BYPASS_URL=${bypass_url}", + ] + + if $token { + $environment = $_default_env_vars + ["RD_TOKEN=${token}"] + } else { + $environment = $_default_env_vars + ["RD_USER=${user}", "RD_PASSWORD=${password}"] + } + + exec { 'Check rundeck cli connection': + command => 'rd system info', + path => ['/bin', '/usr/bin', '/usr/local/bin'], + environment => $environment, + tries => 60, + try_sleep => 5, + unless => 'rd system info &> /dev/null', + require => Package['rundeck-cli'], + } + + $projects.each |$_name, $_attr| { + rundeck::config::project { $_name: + * => $_attr, + require => Exec['Check rundeck cli connection'], + } + } +} diff --git a/manifests/config/project.pp b/manifests/config/project.pp new file mode 100644 index 000000000..d2922e262 --- /dev/null +++ b/manifests/config/project.pp @@ -0,0 +1,63 @@ +# @summary This define will create and manage a rundeck project. +# +# @example Basic usage. +# rundeck::config::project { 'MyProject': +# config => { +# 'project.description' => 'My test project', +# 'project.disable.schedule' => 'false', +# }, +# } +# +# @param update_method +# set: Overwrite all configuration properties for a project. Any config keys not included will be removed. +# update: Modify configuration properties for a project. Only the specified keys will be updated. +# @param config +# Configuration properties for a project. +# +define rundeck::config::project ( + Enum['set', 'update'] $update_method = 'update', + Hash[String, String] $config = { + 'project.description' => "${name} project", + 'project.label' => $name, + 'project.disable.executions' => 'false', + 'project.disable.schedule' => 'false', + 'project.execution.history.cleanup.batch' => '500', + 'project.execution.history.cleanup.enabled' => 'true', + 'project.execution.history.cleanup.retention.days' => '60', + 'project.execution.history.cleanup.retention.minimum' => '50', + 'project.execution.history.cleanup.schedule' => '0 0 0 1/1 * ? *', + 'project.jobs.gui.groupExpandLevel' => '1', + }, +) { + include rundeck::cli + + $_default_cfg = { + 'project.name' => $name, + } + + $_final_cfg = $config + $_default_cfg + + $_cmd_line_cfg = $_final_cfg.map |$_k, $_v| { + "--${_k}=${_v}" + } + + $_project_diff = $update_method ? { + 'set' => "rd_project_diff.sh '${name}' ${update_method} '${_final_cfg.to_json}'", + default => "rd_project_diff.sh '${name}' ${update_method} '${_final_cfg.to_json}' '${_final_cfg.keys}'", + } + + exec { + default: + path => ['/bin', '/usr/bin', '/usr/local/bin'], + environment => $rundeck::cli::environment, + ; + "Create rundeck project: ${name}": + command => "rd projects create -p ${name}", + unless => "rd projects info -p ${name}", + ; + "Manage rundeck project: ${name}": + command => "rd projects configure ${update_method} -p ${name} -- ${_cmd_line_cfg.shellquote}", + unless => $_project_diff, + ; + } +} diff --git a/spec/classes/cli_spec.rb b/spec/classes/cli_spec.rb new file mode 100644 index 000000000..320fbffad --- /dev/null +++ b/spec/classes/cli_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'rundeck::cli' do + on_supported_os.each do |os, facts| + context "on #{os}" do + let :facts do + facts + end + + context 'with default parameters' do + it { is_expected.to compile } + + it { is_expected.to contain_package('jq').with(ensure: 'present') } + + case facts[:os]['family'] + when 'RedHat' + it do + is_expected.to contain_yumrepo('rundeck').with( + baseurl: 'https://packages.rundeck.com/pagerduty/rundeck/rpm_any/rpm_any/$basearch', + repo_gpgcheck: 1, + gpgcheck: 0, + enabled: 1, + gpgkey: 'https://packages.rundeck.com/pagerduty/rundeck/gpgkey' + ).that_comes_before('Package[rundeck-cli]') + end + when 'Debian' + it do + is_expected.to contain_apt__source('rundeck').with( + location: 'https://packages.rundeck.com/pagerduty/rundeck/any', + release: 'any', + repos: 'main', + key: { + 'name' => 'rundeck.asc', + 'content' => %r{^-----BEGIN PGP PUBLIC KEY BLOCK-----}, + } + ).that_comes_before('Package[rundeck-cli]') + end + + it { is_expected.to contain_class('apt::update').that_comes_before('Package[rundeck-cli]') } + it { is_expected.to contain_package('rundeck-cli').with(ensure: 'installed') } + it { is_expected.to contain_file('/usr/local/bin/rd_project_diff.sh').with(ensure: 'file', mode: '0755') } + + it do + is_expected.to contain_exec('Check rundeck cli connection').with( + command: 'rd system info', + path: ['/bin', '/usr/bin', '/usr/local/bin'], + environment: [ + 'RD_FORMAT=json', + 'RD_URL=http://localhost:4440', + 'RD_BYPASS_URL=http://localhost:4440', + 'RD_USER=admin', + 'RD_PASSWORD=admin', + ], + tries: 60, + try_sleep: 5, + unless: 'rd system info &> /dev/null' + ).that_requires('Package[rundeck-cli]') + end + end + end + + context 'with different urls and token auth' do + let(:params) do + { + url: 'http://rundeck01.example.com', + bypass_url: 'http://rundeck.example.com', + token: 'very_secure' + } + end + + it do + is_expected.to contain_exec('Check rundeck cli connection').with( + environment: [ + 'RD_FORMAT=json', + 'RD_URL=http://rundeck01.example.com', + 'RD_BYPASS_URL=http://rundeck.example.com', + 'RD_TOKEN=very_secure', + ] + ) + end + end + + context 'with projects config' do + let(:params) do + { + projects: { + 'MyProject' => { + 'update_method' => 'set', + 'config' => { + 'project.description' => 'This is My rundeck project', + 'project.disable.executions' => 'false', + }, + }, + 'TestProject' => { + 'config' => { + 'project.description' => 'This is a rundeck test project', + 'project.disable.schedule' => 'false', + }, + }, + }, + } + end + + it do + is_expected.to contain_rundeck__config__project('MyProject').with( + update_method: 'set', + config: { + 'project.description' => 'This is My rundeck project', + 'project.disable.executions' => 'false', + } + ) + end + + it { is_expected.to contain_exec('Create rundeck project: MyProject') } + it { is_expected.to contain_exec('Manage rundeck project: MyProject') } + + it do + is_expected.to contain_rundeck__config__project('TestProject').with( + config: { + 'project.description' => 'This is a rundeck test project', + 'project.disable.schedule' => 'false', + } + ) + end + + it { is_expected.to contain_exec('Create rundeck project: TestProject') } + it { is_expected.to contain_exec('Manage rundeck project: TestProject') } + end + end + end +end diff --git a/spec/defines/config/project_spec.rb b/spec/defines/config/project_spec.rb new file mode 100644 index 000000000..fbac0ef00 --- /dev/null +++ b/spec/defines/config/project_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'rundeck::config::project', type: :define do + on_supported_os.each do |os, facts| + context "on #{os}" do + let :facts do + facts + end + + context 'Add rundeck project: MyProject with defaults' do + name = 'MyProject' + + let(:title) { name } + + it do + is_expected.to contain_rundeck__config__project('MyProject').with( + update_method: 'update', + config: { + 'project.description' => 'MyProject project', + 'project.label' => 'MyProject', + 'project.disable.executions' => 'false', + 'project.disable.schedule' => 'false', + 'project.execution.history.cleanup.batch' => '500', + 'project.execution.history.cleanup.enabled' => 'true', + 'project.execution.history.cleanup.retention.days' => '60', + 'project.execution.history.cleanup.retention.minimum' => '50', + 'project.execution.history.cleanup.schedule' => '0 0 0 1/1 * ? *', + 'project.jobs.gui.groupExpandLevel' => '1', + } + ) + end + + it { is_expected.to contain_exec('Create rundeck project: MyProject') } + it { is_expected.to contain_exec('Manage rundeck project: MyProject') } + end + + context 'Add rundeck project: TestProject with update_method = set and custom config' do + name = 'TestProject' + + let(:title) { name } + let(:params) do + { + update_method: 'set', + config: { + 'project.description' => 'This is a rundeck test project', + 'project.disable.executions' => 'false', + }, + } + end + + it do + is_expected.to contain_rundeck__config__project('TestProject').with( + update_method: 'set', + config: { + 'project.description' => 'This is a rundeck test project', + 'project.disable.executions' => 'false', + } + ) + end + + it { is_expected.to contain_exec('Create rundeck project: TestProject') } + it { is_expected.to contain_exec('Manage rundeck project: TestProject') } + end + end + end +end diff --git a/types/project.pp b/types/project.pp new file mode 100644 index 000000000..493f9e279 --- /dev/null +++ b/types/project.pp @@ -0,0 +1,5 @@ +# Rundeck project config type. +type Rundeck::Project = Struct[{ + Optional['config'] => Hash[String, String], + Optional['update_method'] => String, +}] From a17ee8d84d5fbd867c361b805bab3703dd8d026d Mon Sep 17 00:00:00 2001 From: Joris29 Date: Tue, 16 Jan 2024 08:22:54 +0100 Subject: [PATCH 2/5] Add cli support in rundeck class and update unit tests --- manifests/init.pp | 43 +++++++++++++++++++++-- spec/classes/config/ssl_spec.rb | 16 ++++----- spec/classes/config_spec.rb | 18 ++++++---- spec/classes/install_spec.rb | 31 +++++----------- spec/classes/rundeck_spec.rb | 17 +++++++-- spec/classes/service_spec.rb | 6 ++-- spec/defines/config/aclpolicyfile_spec.rb | 12 +++---- 7 files changed, 91 insertions(+), 52 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 8e98f393d..5ee70d7b4 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,10 +1,13 @@ # @summary Class to manage installation and configuration of Rundeck. # -# @param manage_repo -# Whether to manage the package repository. +# @param override_dir +# An absolute path to the overrides directory. +# Examples/defaults for yumrepo can be found at RedHat.yaml, and for apt at Debian.yaml # @param repo_config # A hash of repository attributes for configuring the rundeck package repositories. # Examples/defaults for yumrepo can be found at RedHat.yaml, and for apt at Debian.yaml +# @param manage_repo +# Whether to manage the package repository. # @param package_ensure # Ensure the state of the rundeck package, either present, absent or a specific version. # @param manage_home @@ -35,6 +38,8 @@ # Wheter to enable cluster mode. # @param execution_mode # Set the execution mode to 'active' or 'passive'. +# @param api_token_max_duration +# Set the token max duration. # @param java_home # Set the home directory of java. # @param jvm_args @@ -106,6 +111,18 @@ # Allows you to use your own override template instead to config rundeckd init script. # @param service_script # Allows you to use your own override template instead of the default from the package maintainer for rundeckd init script. +# @param manage_cli +# Whether to manage rundeck cli config and resource with the rundeck class or not. +# @param cli_version +# Ensure the state of the rundeck cli package, either present, absent or a specific version. +# @param cli_user +# Cli user to authenticate. +# @param cli_password +# Cli password to authenticate. +# @param cli_token +# Cli token to authenticate. +# @param cli_projects +# Cli projects config. # class rundeck ( Stdlib::Absolutepath $override_dir, @@ -222,6 +239,12 @@ Boolean $service_notify = true, Optional[String[1]] $service_config = undef, Optional[String[1]] $service_script = undef, + Boolean $manage_cli = true, + String[1] $cli_version = 'installed', + String[1] $cli_user = 'admin', + String[1] $cli_password = 'admin', + Optional[String[8]] $cli_token = undef, + Hash[String, Rundeck::Project] $cli_projects = {}, ) { validate_rd_policy($admin_policies) validate_rd_policy($api_policies) @@ -239,4 +262,20 @@ -> Class['rundeck::config'] -> Class['rundeck::service'] } + + if $manage_cli { + class { 'rundeck::cli': + manage_repo => false, + version => $cli_version, + url => $rundeck::config::framework_config['framework.server.url'], + bypass_url => $grails_server_url, + user => $cli_user, + password => $cli_password, + token => $cli_token, + projects => $cli_projects, + } + + Class['rundeck::service'] + -> Class['rundeck::cli'] + } } diff --git a/spec/classes/config/ssl_spec.rb b/spec/classes/config/ssl_spec.rb index 4f17ed721..0ee3f38a9 100644 --- a/spec/classes/config/ssl_spec.rb +++ b/spec/classes/config/ssl_spec.rb @@ -26,7 +26,7 @@ it { is_expected.to contain_file('/etc/rundeck/ssl').with('ensure' => 'directory') } it { is_expected.to contain_file('/etc/rundeck/ssl/ssl.properties') } - it { + it do is_expected.to contain_java_ks('keystore').with( ensure: 'present', certificate: '/etc/rundeck/ssl/rundeck.crt', @@ -35,15 +35,15 @@ password: 'adminadmin', target: '/etc/rundeck/ssl/keystore' ) - } + end - it { + it do is_expected.to contain_java_ks('truststore').with( ensure: 'present', password: 'adminadmin', target: '/etc/rundeck/ssl/truststore' ) - } + end ssl_details.each do |key, value| it 'generates valid content for ssl.properties' do @@ -61,19 +61,19 @@ } end - it { + it do is_expected.to contain_java_ks('keystore').with( ensure: 'present', destkeypass: 'verysecure' ) - } + end - it { + it do is_expected.to contain_java_ks('truststore').with( ensure: 'present', destkeypass: 'verysecure' ) - } + end it 'generates valid content for ssl.properties' do content = catalogue.resource('file', '/etc/rundeck/ssl/ssl.properties')[:content] diff --git a/spec/classes/config_spec.rb b/spec/classes/config_spec.rb index 0cabe488b..3b16e1799 100644 --- a/spec/classes/config_spec.rb +++ b/spec/classes/config_spec.rb @@ -12,11 +12,15 @@ facts end - context 'without any parameters test rundeck::config' do - it { is_expected.to contain_file('/var/lib/rundeck').with('ensure' => 'directory') } - it { is_expected.to contain_file('/var/lib/rundeck/libext').with('ensure' => 'directory') } - it { is_expected.to contain_file('/etc/rundeck').with('ensure' => 'directory') } - it { is_expected.to contain_file('/var/log/rundeck').with('ensure' => 'directory') } + context 'with default parameters test rundeck::config' do + it { is_expected.to contain_file('/var/lib/rundeck').with(ensure: 'directory') } + it { is_expected.to contain_file('/var/lib/rundeck/libext').with(ensure: 'directory') } + it { is_expected.to contain_file('/etc/rundeck').with(ensure: 'directory') } + it { is_expected.to contain_file('/var/lib/rundeck/var').with(ensure: 'directory') } + it { is_expected.to contain_file('/var/lib/rundeck/var/tmp').with(ensure: 'directory') } + it { is_expected.to contain_file('/var/lib/rundeck/var/logs').with(ensure: 'directory') } + + it { is_expected.to contain_file('/var/log/rundeck').with(ensure: 'directory') } it { is_expected.to contain_file('/etc/rundeck/log4j2.properties') } @@ -46,8 +50,8 @@ it { is_expected.to contain_class('rundeck::config::jaas_auth') } it { is_expected.to contain_class('rundeck::config::framework') } - it { is_expected.to contain_file('/etc/rundeck/project.properties').with('ensure' => 'absent') } - it { is_expected.to contain_file('/etc/rundeck/rundeck-config.properties').with('ensure' => 'file') } + it { is_expected.to contain_file('/etc/rundeck/project.properties').with(ensure: 'absent') } + it { is_expected.to contain_file('/etc/rundeck/rundeck-config.properties').with(ensure: 'file') } it 'generates valid content for rundeck-config.properties' do content = catalogue.resource('file', '/etc/rundeck/rundeck-config.properties')[:content] diff --git a/spec/classes/install_spec.rb b/spec/classes/install_spec.rb index fb928b631..04202a186 100644 --- a/spec/classes/install_spec.rb +++ b/spec/classes/install_spec.rb @@ -9,9 +9,8 @@ facts end - context 'without any parameters test rundeck::install' do - let(:params) { {} } - + context 'with default parameters test rundeck::install' do + it { is_expected.not_to contain_group('rundeck') } it { is_expected.not_to contain_user('rundeck') } case facts[:os]['family'] @@ -35,7 +34,7 @@ 'name' => 'rundeck.asc', 'content' => %r{^-----BEGIN PGP PUBLIC KEY BLOCK-----}, } - ) + ).that_comes_before('Package[rundeck]') end it { is_expected.to contain_class('apt::update').that_comes_before('Package[rundeck]') } @@ -54,13 +53,13 @@ } end - it { is_expected.to contain_group('A1234').with('ensure' => 'present') } + it { is_expected.to contain_group('A1234').with(ensure: 'present') } - it { is_expected.to contain_group('rundeck').with('ensure' => 'absent') } + it { is_expected.to contain_group('rundeck').with(ensure: 'absent') } - it { is_expected.to contain_user('A1234').with('ensure' => 'present') } + it { is_expected.to contain_user('A1234').with(ensure: 'present') } - it { is_expected.to contain_user('rundeck').with('ensure' => 'absent') } + it { is_expected.to contain_user('rundeck').with(ensure: 'absent') } end context 'different user and group with ids' do @@ -75,20 +74,8 @@ } end - it do - is_expected.to contain_group('A1234').with( - 'ensure' => 'present', - 'gid' => 10_000 - ) - end - - it do - is_expected.to contain_user('A1234').with( - 'ensure' => 'present', - 'gid' => '10000', - 'uid' => '10000' - ) - end + it { is_expected.to contain_group('A1234').with(ensure: 'present', gid: 10_000) } + it { is_expected.to contain_user('A1234').with(ensure: 'present', gid: 10_000, uid: 10_000) } end end end diff --git a/spec/classes/rundeck_spec.rb b/spec/classes/rundeck_spec.rb index 983cff476..148471ff7 100644 --- a/spec/classes/rundeck_spec.rb +++ b/spec/classes/rundeck_spec.rb @@ -9,9 +9,7 @@ facts end - context 'without any parameters test rundeck' do - let(:params) { {} } - + context 'with default parameters test rundeck' do it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('rundeck::install').that_comes_before('Class[rundeck::config]') } it { is_expected.to contain_class('rundeck::config').that_notifies('Class[rundeck::service]') } @@ -19,6 +17,7 @@ it { is_expected.to contain_class('rundeck::config::jaas_auth') } it { is_expected.to contain_class('rundeck::config::framework') } it { is_expected.not_to contain_class('rundeck::config::ssl') } + it { is_expected.to contain_class('rundeck::cli') } end context 'with service_notify => false' do @@ -31,6 +30,7 @@ it { is_expected.to contain_class('rundeck::install').that_comes_before('Class[rundeck::config]') } it { is_expected.to contain_class('rundeck::config').that_comes_before('Class[rundeck::service]') } it { is_expected.to contain_class('rundeck::service') } + it { is_expected.to contain_class('rundeck::cli') } end context 'with ssl_enabled => true' do @@ -57,6 +57,17 @@ expect(content).to include('rundeck.server.uuid = ac7c2cbd-14fa-5ba3-b3f2-d436e9b8a3b0') end end + + context 'with manage_cli => false' do + let(:params) do + { + manage_cli: false + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.not_to contain_class('rundeck::cli') } + end end end end diff --git a/spec/classes/service_spec.rb b/spec/classes/service_spec.rb index 23428d89e..615873a28 100644 --- a/spec/classes/service_spec.rb +++ b/spec/classes/service_spec.rb @@ -9,10 +9,8 @@ facts end - context 'without any parameters test rundeck::service' do - let(:params) { {} } - - it { is_expected.to contain_service('rundeckd') } + context 'with default parameters test rundeck::service' do + it { is_expected.to contain_service('rundeckd').with(ensure: 'running') } end end end diff --git a/spec/defines/config/aclpolicyfile_spec.rb b/spec/defines/config/aclpolicyfile_spec.rb index 133bb9f71..a58e11ad8 100644 --- a/spec/defines/config/aclpolicyfile_spec.rb +++ b/spec/defines/config/aclpolicyfile_spec.rb @@ -91,14 +91,14 @@ } end - it { + it do is_expected.to contain_file('/etc/rundeck/test.aclpolicy').with( owner: 'rundeck', group: 'rundeck', mode: '0644', content: test_acl ) - } + end end context 'with test acl and custom parameters' do @@ -112,22 +112,22 @@ } end - it { + it do is_expected.to contain_file('/etc/rundeck-acl').with( ensure: 'directory', owner: 'myUser', group: 'myGroup', mode: '0755' ) - } + end - it { + it do is_expected.to contain_file('/etc/rundeck-acl/test.aclpolicy').with( owner: 'myUser', group: 'myGroup', mode: '0644', content: test_acl ) - } + end end end From bbb118d509e135ce74d79a92d79ce885563d4907 Mon Sep 17 00:00:00 2001 From: Joris29 Date: Tue, 16 Jan 2024 08:24:45 +0100 Subject: [PATCH 3/5] Update module references --- REFERENCE.md | 268 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 256 insertions(+), 12 deletions(-) diff --git a/REFERENCE.md b/REFERENCE.md index e162c6e75..88726da45 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -9,6 +9,7 @@ #### Public Classes * [`rundeck`](#rundeck): Class to manage installation and configuration of Rundeck. +* [`rundeck::cli`](#rundeck--cli): Class to manage installation and configuration of Rundeck CLI. #### Private Classes @@ -23,6 +24,7 @@ * [`rundeck::config::aclpolicyfile`](#rundeck--config--aclpolicyfile): This define will create a custom acl policy file. * [`rundeck::config::plugin`](#rundeck--config--plugin): This define will install a rundeck plugin. +* [`rundeck::config::project`](#rundeck--config--project): This define will create and manage a rundeck project. ### Functions @@ -35,6 +37,7 @@ * [`Rundeck::Key_storage_config`](#Rundeck--Key_storage_config): Rundeck key storage config type. * [`Rundeck::Loglevel`](#Rundeck--Loglevel): Rundeck log level type. * [`Rundeck::Mail_config`](#Rundeck--Mail_config): Rundeck mail config type. +* [`Rundeck::Project`](#Rundeck--Project): Rundeck project config type. ## Classes @@ -46,8 +49,9 @@ Class to manage installation and configuration of Rundeck. The following parameters are available in the `rundeck` class: -* [`manage_repo`](#-rundeck--manage_repo) +* [`override_dir`](#-rundeck--override_dir) * [`repo_config`](#-rundeck--repo_config) +* [`manage_repo`](#-rundeck--manage_repo) * [`package_ensure`](#-rundeck--package_ensure) * [`manage_home`](#-rundeck--manage_home) * [`user`](#-rundeck--user) @@ -63,6 +67,7 @@ The following parameters are available in the `rundeck` class: * [`grails_server_url`](#-rundeck--grails_server_url) * [`clustermode_enabled`](#-rundeck--clustermode_enabled) * [`execution_mode`](#-rundeck--execution_mode) +* [`api_token_max_duration`](#-rundeck--api_token_max_duration) * [`java_home`](#-rundeck--java_home) * [`jvm_args`](#-rundeck--jvm_args) * [`quartz_job_threadcount`](#-rundeck--quartz_job_threadcount) @@ -98,16 +103,19 @@ The following parameters are available in the `rundeck` class: * [`service_notify`](#-rundeck--service_notify) * [`service_config`](#-rundeck--service_config) * [`service_script`](#-rundeck--service_script) -* [`override_dir`](#-rundeck--override_dir) -* [`api_token_max_duration`](#-rundeck--api_token_max_duration) - -##### `manage_repo` +* [`manage_cli`](#-rundeck--manage_cli) +* [`cli_version`](#-rundeck--cli_version) +* [`cli_user`](#-rundeck--cli_user) +* [`cli_password`](#-rundeck--cli_password) +* [`cli_token`](#-rundeck--cli_token) +* [`cli_projects`](#-rundeck--cli_projects) -Data type: `Boolean` +##### `override_dir` -Whether to manage the package repository. +Data type: `Stdlib::Absolutepath` -Default value: `true` +An absolute path to the overrides directory. +Examples/defaults for yumrepo can be found at RedHat.yaml, and for apt at Debian.yaml ##### `repo_config` @@ -116,6 +124,14 @@ Data type: `Hash` A hash of repository attributes for configuring the rundeck package repositories. Examples/defaults for yumrepo can be found at RedHat.yaml, and for apt at Debian.yaml +##### `manage_repo` + +Data type: `Boolean` + +Whether to manage the package repository. + +Default value: `true` + ##### `package_ensure` Data type: `String[1]` @@ -292,6 +308,14 @@ Set the execution mode to 'active' or 'passive'. Default value: `'active'` +##### `api_token_max_duration` + +Data type: `String[1]` + +Set the token max duration. + +Default value: `'30d'` + ##### `java_home` Data type: `Optional[Stdlib::Absolutepath]` @@ -589,19 +613,170 @@ Allows you to use your own override template instead of the default from the pac Default value: `undef` -##### `override_dir` +##### `manage_cli` -Data type: `Stdlib::Absolutepath` +Data type: `Boolean` +Whether to manage rundeck cli config and resource with the rundeck class or not. +Default value: `true` -##### `api_token_max_duration` +##### `cli_version` Data type: `String[1]` +Ensure the state of the rundeck cli package, either present, absent or a specific version. +Default value: `'installed'` -Default value: `'30d'` +##### `cli_user` + +Data type: `String[1]` + +Cli user to authenticate. + +Default value: `'admin'` + +##### `cli_password` + +Data type: `String[1]` + +Cli password to authenticate. + +Default value: `'admin'` + +##### `cli_token` + +Data type: `Optional[String[8]]` + +Cli token to authenticate. + +Default value: `undef` + +##### `cli_projects` + +Data type: `Hash[String, Rundeck::Project]` + +Cli projects config. + +Default value: `{}` + +### `rundeck::cli` + +Class to manage installation and configuration of Rundeck CLI. + +#### Examples + +##### Use cli with token and project config. + +```puppet +class { 'rundeck::cli': + manage_repo => false, + url => 'https://rundeck01.example.com', + bypass_url => 'https://rundeck.example.com', + token => 'very_secure', + projects => { + 'MyProject' => { + 'update_method' => 'set', + 'config' => { + 'project.description' => 'This is My rundeck project', + 'project.disable.executions' => 'false', + }, + }, + 'TestProject' => { + 'config' => { + 'project.description' => 'This is a rundeck test project', + 'project.disable.schedule' => 'false', + }, + }, + }, +} +``` + +#### Parameters + +The following parameters are available in the `rundeck::cli` class: + +* [`repo_config`](#-rundeck--cli--repo_config) +* [`manage_repo`](#-rundeck--cli--manage_repo) +* [`version`](#-rundeck--cli--version) +* [`url`](#-rundeck--cli--url) +* [`bypass_url`](#-rundeck--cli--bypass_url) +* [`user`](#-rundeck--cli--user) +* [`password`](#-rundeck--cli--password) +* [`token`](#-rundeck--cli--token) +* [`projects`](#-rundeck--cli--projects) + +##### `repo_config` + +Data type: `Hash` + +A hash of repository attributes for configuring the rundeck cli package repositories. +Examples/defaults for yumrepo can be found at RedHat.yaml, and for apt at Debian.yaml + +##### `manage_repo` + +Data type: `Boolean` + +Whether to manage the cli package repository. + +Default value: `true` + +##### `version` + +Data type: `String[1]` + +Ensure the state of the rundeck cli package, either present, absent or a specific version. + +Default value: `'installed'` + +##### `url` + +Data type: `Stdlib::HTTPUrl` + +Rundeck instance/api url. + +Default value: `'http://localhost:4440'` + +##### `bypass_url` + +Data type: `Stdlib::HTTPUrl` + +Rundeck external url to bypass. This will rewrite any redirect to $bypass_url as $url + +Default value: `'http://localhost:4440'` + +##### `user` + +Data type: `String[1]` + +Cli user to authenticate. + +Default value: `'admin'` + +##### `password` + +Data type: `String[1]` + +Cli password to authenticate. + +Default value: `'admin'` + +##### `token` + +Data type: `Optional[String[8]]` + +Cli token to authenticate. + +Default value: `undef` + +##### `projects` + +Data type: `Hash[String, Rundeck::Project]` + +Cli projects config. See example for structure and rundeck::config::project for available params. + +Default value: `{}` ## Defined types @@ -760,6 +935,62 @@ Get the plugin trough a proxy server. Default value: `undef` +### `rundeck::config::project` + +This define will create and manage a rundeck project. + +#### Examples + +##### Basic usage. + +```puppet +rundeck::config::project { 'MyProject': + config => { + 'project.description' => 'My test project', + 'project.disable.schedule' => 'false', + }, +} +``` + +#### Parameters + +The following parameters are available in the `rundeck::config::project` defined type: + +* [`update_method`](#-rundeck--config--project--update_method) +* [`config`](#-rundeck--config--project--config) + +##### `update_method` + +Data type: `Enum['set', 'update']` + +set: Overwrite all configuration properties for a project. Any config keys not included will be removed. +update: Modify configuration properties for a project. Only the specified keys will be updated. + +Default value: `'update'` + +##### `config` + +Data type: `Hash[String, String]` + +Configuration properties for a project. + +Default value: + +```puppet +{ + 'project.description' => "${name} project", + 'project.label' => $name, + 'project.disable.executions' => 'false', + 'project.disable.schedule' => 'false', + 'project.execution.history.cleanup.batch' => '500', + 'project.execution.history.cleanup.enabled' => 'true', + 'project.execution.history.cleanup.retention.days' => '60', + 'project.execution.history.cleanup.retention.minimum' => '50', + 'project.execution.history.cleanup.schedule' => '0 0 0 1/1 * ? *', + 'project.jobs.gui.groupExpandLevel' => '1', + } +``` + ## Functions ### `validate_rd_policy` @@ -847,3 +1078,16 @@ Struct[{ }] ``` +### `Rundeck::Project` + +Rundeck project config type. + +Alias of + +```puppet +Struct[{ + Optional['config'] => Hash[String, String], + Optional['update_method'] => String, +}] +``` + From 3b733e5e1fc5bd21f3a655937110eca85b0abfd6 Mon Sep 17 00:00:00 2001 From: Joris29 Date: Thu, 25 Jan 2024 14:58:12 +0100 Subject: [PATCH 4/5] Drop CentOS 7 support --- metadata.json | 1 - 1 file changed, 1 deletion(-) diff --git a/metadata.json b/metadata.json index 370383c2c..e390efb0f 100644 --- a/metadata.json +++ b/metadata.json @@ -45,7 +45,6 @@ { "operatingsystem": "CentOS", "operatingsystemrelease": [ - "7", "8", "9" ] From b4ec6cca54827b3d67c3a9f852183e4943bed29f Mon Sep 17 00:00:00 2001 From: Joris29 Date: Thu, 25 Jan 2024 15:29:00 +0100 Subject: [PATCH 5/5] Update readme --- README.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 426c90760..b311c300c 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,20 @@ On systems that use apt, there's a soft dependency on the [puppetlabs/apt](https ### Beginning with rundeck -To install a server with the default options: +To install a server and cli with the default options: ```puppet include rundeck ``` +### Beginning with rundeck cli + +To install rundeck cli with the default options: + +```puppet +include rundeck::cli +``` + ## Usage ### Configure rundeck to connect to a MySQL database @@ -185,6 +193,61 @@ class { 'rundeck': } ``` +### Configure rundeck class with projects + +To add and manage rundeck projects through cli with the rundeck class following code can be used. + +```puppet +class { 'rundeck': + 'cli_token' => 'very_secure', + 'cli_projects' => { + 'MyProject' => { + 'update_method' => 'set', + 'config' => { + 'project.description' => 'This is My rundeck project', + 'project.disable.executions' => 'false', + }, + }, + 'TestProject' => { + 'config' => { + 'project.description' => 'This is a rundeck test project', + 'project.disable.schedule' => 'false', + }, + }, + }, +} +``` + +### Configure rundeck cli class with projects separately + +To add and manage rundeck projects through cli with the rundeck class following code can be used. + +```puppet +class { 'rundeck': + 'manage_cli' => false, +} + +class { 'rundeck::cli': + 'manage_repo' => false, + 'token' => 'very_secure', + 'projects' => { + 'MyProject' => { + 'update_method' => 'set', + 'config' => { + 'project.description' => 'This is My rundeck project', + 'project.disable.executions' => 'false', + }, + }, + 'TestProject' => { + 'config' => { + 'project.description' => 'This is a rundeck test project', + 'project.disable.schedule' => 'false', + }, + }, + }, +} +``` + ## Reference See [REFERENCE.md](https://github.com/voxpupuli/puppet-rundeck/blob/master/REFERENCE.md) @@ -193,11 +256,14 @@ See [REFERENCE.md](https://github.com/voxpupuli/puppet-rundeck/blob/master/REFER This module is tested on the following platforms: -- CentOS 6 -- CentOS 7 -- Debian 8 +- CentOS 8 +- CentOS 9 +- Debian 10 +- Debian 11 - RedHat 8 -- Ubuntu 16.04 +- Ubuntu 18.04 +- Ubuntu 20.04 +- Ubuntu 22.04 It is tested with the OSS version of Puppet only.