Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the docker-compose-plugin via 'docker compose' instead of 'docker-compose' #975

Merged
merged 14 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
30 changes: 14 additions & 16 deletions lib/puppet/provider/docker_compose/ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

has_command(:docker, 'docker')

has_command(:dockercompose, 'docker-compose')

def set_tmpdir
return unless resource[:tmpdir]

Expand All @@ -28,8 +26,8 @@ def exists?
set_tmpdir

# get merged config using docker-compose config
args = [compose_files, '-p', name, 'config'].insert(3, resource[:options]).compact
compose_output = Puppet::Util::Yaml.safe_load(execute([command(:dockercompose)] + args, combine: false), [Symbol])
args = ['compose', compose_files, '-p', name, 'config'].insert(3, resource[:options]).compact
compose_output = Puppet::Util::Yaml.safe_load(execute([command(:docker)] + args, combine: false), [Symbol])

containers = docker([
'ps',
Expand Down Expand Up @@ -76,32 +74,32 @@ def get_image(service_name, compose_services)

def create
Puppet.info("Running compose project #{name}")
args = [compose_files, '-p', name, 'up', '-d', '--remove-orphans'].insert(3, resource[:options]).insert(5, resource[:up_args]).compact
dockercompose(args)
args = ['compose', compose_files, '-p', name, 'up', '-d', '--remove-orphans'].insert(3, resource[:options]).insert(5, resource[:up_args]).compact
docker(args)
return unless resource[:scale]

instructions = resource[:scale].map { |k, v| "#{k}=#{v}" }
Puppet.info("Scaling compose project #{name}: #{instructions.join(' ')}")
args = [compose_files, '-p', name, 'scale'].insert(3, resource[:options]).compact + instructions
dockercompose(args)
args = ['compose', compose_files, '-p', name, 'scale'].insert(3, resource[:options]).compact + instructions
docker(args)
end

def destroy
Puppet.info("Removing all containers for compose project #{name}")
kill_args = [compose_files, '-p', name, 'kill'].insert(3, resource[:options]).compact
dockercompose(kill_args)
rm_args = [compose_files, '-p', name, 'rm', '--force', '-v'].insert(3, resource[:options]).compact
dockercompose(rm_args)
kill_args = ['compose', compose_files, '-p', name, 'kill'].insert(3, resource[:options]).compact
docker(kill_args)
rm_args = ['compose', compose_files, '-p', name, 'rm', '--force', '-v'].insert(3, resource[:options]).compact
docker(rm_args)
end

def restart
return unless exists?

Puppet.info("Rebuilding and Restarting all containers for compose project #{name}")
kill_args = [compose_files, '-p', name, 'kill'].insert(3, resource[:options]).compact
dockercompose(kill_args)
build_args = [compose_files, '-p', name, 'build'].insert(3, resource[:options]).compact
dockercompose(build_args)
kill_args = ['compose', compose_files, '-p', name, 'kill'].insert(3, resource[:options]).compact
docker(kill_args)
build_args = ['compose', compose_files, '-p', name, 'build'].insert(3, resource[:options]).compact
docker(build_args)
create
end

Expand Down
130 changes: 30 additions & 100 deletions manifests/compose.pp
Original file line number Diff line number Diff line change
Expand Up @@ -7,118 +7,48 @@
# @param version
# The version of Docker Compose to install.
#
# @param install_path
# The path where to install Docker Compose.
#
# @param symlink_name
# The name of the symlink created pointing to the actual docker-compose binary
# This allows use of own docker-compose wrapper scripts for the times it's
# necessary to set certain things before running the docker-compose binary
#
# @param proxy
# Proxy to use for downloading Docker Compose.
#
# @param base_url
# The base url for installation
# This allows use of a mirror that follows the same layout as the
# official repository
#
# @param raw_url
# Override the raw URL for installation
# The default is to build a URL from baseurl. If rawurl is set, the caller is
# responsible for ensuring the URL points to the correct version and
# architecture.
#
# @param curl_ensure
# Whether or not the curl package is ensured by this module.
#
class docker::compose (
Enum[present,absent] $ensure = present,
Optional[String] $version = $docker::params::compose_version,
Optional[String] $install_path = $docker::params::compose_install_path,
Optional[String] $symlink_name = $docker::params::compose_symlink_name,
Optional[Pattern['^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$']] $proxy = undef,
Optional[String] $base_url = $docker::params::compose_base_url,
Optional[String] $raw_url = undef,
Optional[Boolean] $curl_ensure = $docker::params::curl_ensure,
) inherits docker::params {
if $facts['os']['family'] == 'windows' {
$file_extension = '.exe'
$file_owner = 'Administrator'
} else {
$file_extension = ''
$file_owner = 'root'
}
Enum[present,absent] $ensure = present,
Optional[String] $version = undef,
) {
include docker

$docker_compose_location = "${install_path}/${symlink_name}${file_extension}"
$docker_compose_location_versioned = "${install_path}/docker-compose-${version}${file_extension}"
if $docker::manage_package {
nathanlcarlson marked this conversation as resolved.
Show resolved Hide resolved
include docker::params
nathanlcarlson marked this conversation as resolved.
Show resolved Hide resolved

if $ensure == 'present' {
if $raw_url != undef {
$docker_compose_url = $raw_url
} else {
$docker_compose_url = "${base_url}/${version}/docker-compose-${facts['kernel']}-${facts['os']['hardware']}${file_extension}"
$_version = $version ? {
undef => $docker::params::compose_version,
default => $version,
}

if $proxy != undef {
$proxy_opt = "--proxy ${proxy}"
if $_version and $ensure != 'absent' {
$package_ensure = $_version
} else {
$proxy_opt = ''
$package_ensure = $ensure
}

if $facts['os']['family'] == 'windows' {
$docker_download_command = "if (Invoke-WebRequest ${docker_compose_url} ${proxy_opt} -UseBasicParsing -OutFile \"${docker_compose_location_versioned}\") { exit 0 } else { exit 1}" # lint:ignore:140chars

$parameters = {
'proxy' => $proxy,
'docker_compose_url' => $docker_compose_url,
'docker_compose_location_versioned' => $docker_compose_location_versioned,
case $facts['os']['family'] {
'Debian': {
$_require = $docker::use_upstream_package_source ? {
true => [Apt::Source['docker'], Class['apt::update']],
false => undef,
}
}

exec { "Install Docker Compose ${version}":
command => epp('docker/windows/download_docker_compose.ps1.epp', $parameters),
provider => powershell,
creates => $docker_compose_location_versioned,
'RedHat': {
$_require = $docker::use_upstream_package_source ? {
true => Yumrepo['docker'],
false => undef,
}
}

file { $docker_compose_location:
ensure => 'link',
target => $docker_compose_location_versioned,
require => Exec["Install Docker Compose ${version}"],
}
} else {
if $curl_ensure {
stdlib::ensure_packages(['curl'])
}

exec { "Install Docker Compose ${version}":
path => '/usr/bin/',
cwd => '/tmp',
command => "curl -s -S -L ${proxy_opt} ${docker_compose_url} -o ${docker_compose_location_versioned}",
creates => $docker_compose_location_versioned,
require => Package['curl'],
'Windows': {
fail('The docker compose portion of this module is not supported on Windows')
}

file { $docker_compose_location_versioned:
owner => $file_owner,
mode => '0755',
seltype => 'container_runtime_exec_t',
require => Exec["Install Docker Compose ${version}"],
}

file { $docker_compose_location:
ensure => 'link',
target => $docker_compose_location_versioned,
require => File[$docker_compose_location_versioned],
default: {
fail('The docker compose portion of this module only works on Debian or RedHat')
}
}
} else {
file { $docker_compose_location_versioned:
ensure => absent,
}

file { $docker_compose_location:
ensure => absent,
package { 'docker-compose-plugin':
ensure => $package_ensure,
require => $_require,
}
}
}
7 changes: 1 addition & 6 deletions manifests/params.pp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
$dns = undef
$dns_search = undef
$proxy = undef
$compose_base_url = 'https://github.com/docker/compose/releases/download'
$compose_symlink_name = 'docker-compose'
$compose_version = undef
$no_proxy = undef
$execdriver = undef
$storage_driver = undef
Expand Down Expand Up @@ -90,16 +89,12 @@
$docker_command = 'docker'

if ($facts['os']['family'] == 'windows') {
$compose_install_path = "${facts['docker_program_files_path']}/Docker"
$compose_version = '1.29.2'
$docker_ee_package_name = 'Docker'
$machine_install_path = "${facts['docker_program_files_path']}/Docker"
$tls_cacert = "${facts['docker_program_data_path']}/docker/certs.d/ca.pem"
$tls_cert = "${facts['docker_program_data_path']}/docker/certs.d/server-cert.pem"
$tls_key = "${facts['docker_program_data_path']}/docker/certs.d/server-key.pem"
} else {
$compose_install_path = '/usr/local/bin'
$compose_version = '1.29.2'
$docker_ee_package_name = 'docker-ee'
$machine_install_path = '/usr/local/bin'
$tls_cacert = '/etc/docker/tls/ca.pem'
Expand Down
64 changes: 18 additions & 46 deletions spec/acceptance/compose_v3_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,21 @@

require 'spec_helper_acceptance'

if os[:family] == 'windows'
install_dir = '/cygdrive/c/Program Files/Docker'
file_extension = '.exe'
docker_args = 'docker_ee => true'
tmp_path = 'C:/cygwin64/tmp'
test_container = if %r{2019|2022}.match?(os[:release])
'nanoserver'
else
'nanoserver-sac2016'
end
else
docker_args = ''
install_dir = '/usr/local/bin'
file_extension = ''
tmp_path = '/tmp'
test_container = 'debian'
end
tmp_path = '/tmp'
test_container = 'debian'

describe 'docker compose' do
describe 'docker compose', :win_broken do
before(:all) do
retry_on_error_matching(60, 5, %r{connection failure running}) do
install_code = <<-CODE
class { 'docker': #{docker_args} }
class { 'docker::compose':
version => '1.23.2',
}
class { 'docker': }
class { 'docker::compose': }
CODE
apply_manifest(install_code, catch_failures: true)
end
end

context 'Creating compose v3 projects', :win_broken do
context 'Creating compose v3 projects' do
let(:install_pp) do
<<-MANIFEST
docker_compose { 'web':
Expand All @@ -51,15 +34,15 @@ class { 'docker::compose':
end

it 'has docker compose installed' do
run_shell('docker-compose --help', expect_failures: false)
run_shell('docker compose --help', expect_failures: false)
end

it 'finds a docker container' do
run_shell('docker inspect web_compose_test_1', expect_failures: false)
run_shell('docker inspect web-compose_test_1', expect_failures: false)
end
end

context 'creating compose projects with multi compose files', :win_broken do
context 'creating compose projects with multi compose files' do
before(:all) do
install_pp = <<-MANIFEST
docker_compose { 'web1':
Expand All @@ -75,11 +58,11 @@ class { 'docker::compose':
end

it "finds container with #{test_container} tag" do
run_shell("docker inspect web1_compose_test_1 | grep #{test_container}", acceptable_exit_codes: [0])
run_shell("docker inspect web1-compose_test_1 | grep #{test_container}", acceptable_exit_codes: [0])
end
end

context 'Destroying project with multiple compose files', :win_broken do
context 'Destroying project with multiple compose files' do
let(:destroy_pp) do
<<-MANIFEST
docker_compose { 'web1':
Expand All @@ -105,31 +88,26 @@ class { 'docker::compose':
end

it 'does not find a docker container' do
run_shell('docker inspect web1_compose_test_1', expect_failures: true)
run_shell('docker inspect web1-compose_test_1', expect_failures: true)
end
end

context 'Requesting a specific version of compose' do
let(:version) do
'1.21.2'
'2.25.0'
end

it 'is idempotent' do
pp = <<-MANIFEST
class { 'docker::compose':
version => '#{version}',
version => '#{version}-*',
}
MANIFEST
idempotent_apply(pp)
end

it 'has installed the requested version' do
if os[:family] == 'redhat' && os[:release].to_i == 7
run_shell('sudo mv /usr/local/bin/docker-compose /usr/bin/docker-compose')
run_shell('sudo chmod +x /usr/bin/docker-compose')
end
command = 'docker-compose --version'
command = "export PATH=/usr/local/bin:$PATH && #{command}" if os[:family] == 'redhat'
command = 'docker compose version'

run_shell(command, expect_failures: false) do |r|
expect(r.stdout).to match(%r{#{version}})
Expand All @@ -138,13 +116,9 @@ class { 'docker::compose':
end

context 'Removing docker compose' do
let(:version) do
'1.21.2'
end

after(:all) do
install_pp = <<-MANIFEST
class { 'docker': #{docker_args}}
class { 'docker': }
class { 'docker::compose': }
MANIFEST
apply_manifest(install_pp, catch_failures: true)
Expand All @@ -154,15 +128,13 @@ class { 'docker::compose': }
pp = <<-MANIFEST
class { 'docker::compose':
ensure => absent,
version => '#{version}',
}
MANIFEST
idempotent_apply(pp)
end

it 'has removed the relevant files' do
run_shell("test -e \"#{install_dir}/docker-compose#{file_extension}\"", expect_failures: true)
run_shell("test -e \"#{install_dir}/docker-compose-#{version}#{file_extension}\"", expect_failures: true)
it 'has removed the compose plugin' do
run_shell('docker compose version', expect_failures: true)
end
end
end
Loading
Loading