Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ fixtures:
concat: 'https://github.com/puppetlabs/puppetlabs-concat'
cron_core: 'https://github.com/puppetlabs/puppetlabs-cron_core'
extlib: 'https://github.com/voxpupuli/puppet-extlib'
podman:
repo: 'https://github.com/evgeni/puppet-podman'
branch: 'quadlet'
postgresql: 'https://github.com/puppetlabs/puppetlabs-postgresql'
puppet: 'https://github.com/theforeman/puppet-puppet'
redis: 'https://github.com/voxpupuli/puppet-redis'
Expand Down
36 changes: 23 additions & 13 deletions manifests/config.pp
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@
)
)
$min_puma_threads = pick($foreman::foreman_service_puma_threads_min, $foreman::foreman_service_puma_threads_max)
systemd::dropin_file { 'foreman-service':
filename => 'installer.conf',
unit => "${foreman::foreman_service}.service",
content => template('foreman/foreman.service-overrides.erb'),
notify_service => true,
if $foreman::deployment_mode == 'package' {
systemd::dropin_file { 'foreman-service':
filename => 'installer.conf',
unit => "${foreman::foreman_service}.service",
content => template('foreman/foreman.service-overrides.erb'),
notify_service => true,
}
}

if ! defined(File[$foreman::app_root]) {
Expand Down Expand Up @@ -153,7 +155,13 @@
}

if $foreman::apache {
$listen_socket = '/run/foreman.sock'
if $foreman::deployment_mode == 'container' {
$listen_socket = 'localhost:3000/'
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one was tricky. Apache (or foreman::config::apache) doesn't add a trailing slash to the backend, which then tries to access things like http://localhost:3000users/login, obviously failing

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use systemd socket activation with podman containers. I've used that myself with gunicorn to avoid needing to deal with a firewall (and instead deal with SELinux). Any reason you don't use that now?

See https://github.com/containers/podman/blob/main/docs/tutorials/socket_activation.md#socket-activation-of-containers for more info.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool. I didn't try that (yet), but I also think that the above is a legit bug in our current deployment if for some reason users do not want sockets.

also lol @ "and instead deal with SELinux" ;)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite possible that there's a bug there

$backend_protocol = 'http'
} else {
$listen_socket = '/run/foreman.sock'
$backend_protocol = 'unix'
}

class { 'foreman::config::apache':
app_root => $foreman::app_root,
Expand All @@ -162,7 +170,7 @@
serveraliases => $foreman::serveraliases,
server_port => $foreman::server_port,
server_ssl_port => $foreman::server_ssl_port,
proxy_backend => "unix://${listen_socket}",
proxy_backend => "${backend_protocol}://${listen_socket}",
ssl => $foreman::ssl,
ssl_ca => $foreman::server_ssl_ca,
ssl_chain => $foreman::server_ssl_chain,
Expand Down Expand Up @@ -280,11 +288,13 @@
$foreman_socket_override = undef
}

systemd::dropin_file { 'foreman-socket':
ensure => bool2str($foreman_socket_override =~ Undef, 'absent', 'present'),
filename => 'installer.conf',
unit => "${foreman::foreman_service}.socket",
content => $foreman_socket_override,
notify_service => true,
if $foreman::deployment_mode == 'package' {
systemd::dropin_file { 'foreman-socket':
ensure => bool2str($foreman_socket_override =~ Undef, 'absent', 'present'),
filename => 'installer.conf',
unit => "${foreman::foreman_service}.socket",
content => $foreman_socket_override,
notify_service => true,
}
}
}
3 changes: 3 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@
#
# $provisioning_fcct_location:: The location of the binary to call when transpiling Fedora CoreOS templates.
#
# $deployment_mode:: The way foreman is deployed: packages or container
#
# === Dynflow parameters:
#
# $dynflow_manage_services:: Whether to manage the dynflow services
Expand Down Expand Up @@ -307,6 +309,7 @@
Boolean $register_in_foreman = true,
Optional[Stdlib::Absolutepath] $provisioning_ct_location = undef,
Optional[Stdlib::Absolutepath] $provisioning_fcct_location = undef,
Enum['package', 'container'] $deployment_mode = 'package',
) inherits foreman::params {
assert_type(Array[Stdlib::IP::Address], $trusted_proxies)

Expand Down
45 changes: 37 additions & 8 deletions manifests/service.pp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
Enum['present', 'absent'] $dynflow_orchestrator_ensure = $foreman::dynflow_orchestrator_ensure,
Integer[0] $dynflow_worker_instances = $foreman::dynflow_worker_instances,
Integer[0] $dynflow_worker_concurrency = $foreman::dynflow_worker_concurrency,
Enum['package', 'container'] $deployment_mode = $foreman::deployment_mode,
String[1] $container_image = 'quay.io/evgeni/foreman-rpm:latest',
) {
if $dynflow_manage_services {
foreman::dynflow::worker { 'orchestrator':
Expand All @@ -35,14 +37,41 @@
}
}

service { "${foreman_service}.socket":
ensure => $foreman_service_ensure,
enable => $foreman_service_enable,
}
if $deployment_mode == 'package' {
service { "${foreman_service}.socket":
ensure => $foreman_service_ensure,
enable => $foreman_service_enable,
}

service { $foreman_service:
ensure => $foreman_service_ensure,
enable => $foreman_service_enable,
before => Service["${foreman_service}.socket"],
service { $foreman_service:
ensure => $foreman_service_ensure,
enable => $foreman_service_enable,
before => Service["${foreman_service}.socket"],
}
} else {
file { '/etc/containers/systemd':
ensure => directory,
}
podman::quadlet { 'foreman.container':
ensure => present,
unit_entry => {
'Description' => 'Foreman',
},
service_entry => {
'TimeoutStartSec' => '900',
},
container_entry => {
'Image' => $container_image,
'Volume' => ['/etc/foreman/:/etc/foreman/'],
'AddCapability' => ['CAP_DAC_OVERRIDE', 'CAP_IPC_OWNER'],
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the foreman user inside the container might have a different UID than outside, fucking up file access :/

(I am not sure this is overall a good idea, but here we are for now)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like a nasty hack that we need to resolve prior to going production with this.

'Network' => 'host',
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using Network=host so that we don't need any private networks, fiddling with v6 subnets or exposing ports.

'HostName' => $foreman::servername,
'Notify' => true,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sd_notify from the container, super nice.

},
install_entry => {
'WantedBy' => 'default.target',
},
active => true,
}
}
}
4 changes: 4 additions & 0 deletions metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
{
"name": "puppet/redis",
"version_requirement": ">= 5.0.0 < 12.0.0"
},
{
"name": "southalc/podman",
"version_requirement": ">= 0.6.7 < 1.0.0"
}
],
"requirements": [
Expand Down
20 changes: 20 additions & 0 deletions spec/acceptance/foreman_basic_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,24 @@ class { 'foreman':

it_behaves_like 'the foreman application', { expected_login_url_path: '/users/extlogin' }
end

# needs to happen after GSSAPI, something is wrong with its cleanup
context 'in a Container' do
before(:context) { purge_foreman }
describe 'in a Container' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PUPPET
class { 'foreman':
deployment_mode => 'container',
db_host => 'localhost',
db_manage_rake => false,
Comment on lines +68 to +69
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if these two could be made more "dynamic"?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? That db_manage_rake would be undef by default and the deployment mode determines the value?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, same for host (there is not really a socket in the container)

}
PUPPET
end
end

it_behaves_like 'the foreman application', { deployment_mode: 'container' }
end
end
end
6 changes: 4 additions & 2 deletions spec/support/acceptance/examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
it { is_expected.to be_listening }
end

describe file('/run/foreman.sock') do
it { should be_socket }
if params.fetch(:deployment_mode, 'package') == 'package'
describe file('/run/foreman.sock') do
it { should be_socket }
end
end

describe command("curl -s --cacert /etc/foreman-certs/certificate.pem https://#{host_inventory['fqdn']} -w '\%{redirect_url}' -o /dev/null") do
Expand Down
1 change: 1 addition & 0 deletions spec/support/acceptance/purge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ def purge_foreman
on default, 'apt-get purge -y foreman*', { :acceptable_exit_codes => [0, 100] }
on default, 'apt-get purge -y ruby-hammer-cli-*', { :acceptable_exit_codes => [0, 100] }
end
on default, 'rm -rf /etc/systemd/system/foreman* /etc/containers/systemd/foreman*'

apache_service_name = ['debian', 'ubuntu'].include?(os[:family]) ? 'apache2' : 'httpd'
on default, "systemctl stop #{apache_service_name}", { :acceptable_exit_codes => [0, 5] }
Expand Down