diff --git a/Puppetfile b/Puppetfile index bc5115a..cb189d8 100644 --- a/Puppetfile +++ b/Puppetfile @@ -1,3 +1,4 @@ forge 'https://forgeapi.puppetlabs.com' -mod 'puppetlabs-stdlib', '>= 2.3.3 < 5.0.0' \ No newline at end of file +mod 'puppetlabs-stdlib', '>= 2.3.3 < 5.0.0' +mod 'puppet/archive', '>= 0.5.0' diff --git a/README.md b/README.md index 5e041c9..9c6b9e3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ #puppet-zookeeper -[![Puppet -Forge](http://img.shields.io/puppetforge/v/deric/zookeeper.svg)](https://forge.puppetlabs.com/deric/zookeeper) [![Build Status](https://travis-ci.org/deric/puppet-zookeeper.png?branch=master)](https://travis-ci.org/deric/puppet-zookeeper) +[![Puppet Forge](http://img.shields.io/puppetforge/v/deric/zookeeper.svg)](https://forge.puppetlabs.com/deric/zookeeper) [![Build Status](https://travis-ci.org/deric/puppet-zookeeper.png?branch=master)](https://travis-ci.org/deric/puppet-zookeeper) A puppet receipt for [Apache Zookeeper](http://zookeeper.apache.org/). ZooKeeper is a high-performance coordination service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. @@ -141,16 +140,19 @@ After=network-online.target ## Parameters - `id` - cluster-unique zookeeper's instance id (1-255) - - `datastore` - - `datalogstore` - specifying this configures the `dataLogDir` ZooKeeper config values and allows for transaction logs to be stored in a different location, improving IO performance - - `log_dir` + - `datastore` - configures the zookeeper `dataDir` config parameter + - `datalogstore` - configures the `dataLogDir` ZooKeeper config values and allows for transaction logs to be stored in a different location, improving IO performance + - `log_dir` - Sets java property `zookeeper.log.dir`. Passed to java with `-Dzookeeper.log.dir` - `purge_interval` - automatically will delete ZooKeeper logs (available since ZooKeeper 3.4.0) - `snap_retain_count` - number of snapshots that will be kept after purging (since ZooKeeper 3.4.0) - `min_session_timeout` - the minimum session timeout in milliseconds that the server will allow the client to negotiate. Defaults to 2 times the **tickTime** (since ZooKeeper 3.3.0) - `max_session_timeout` - the maximum session timeout in milliseconds that the server will allow the client to negotiate. Defaults to 20 times the **tickTime** (since ZooKeeper 3.3.0) - - `manage_service` (default: `true`) whether Puppet should ensure running service - - `manage_service_file` when enabled on RHEL 7.0 a systemd config will be managed - - `ensure_account` controls whether `zookeeper` user and group will be ensured (set to `false` to disable this feature) + - `manage_service` (default: `true`) - whether Puppet should ensure running service + - `manage_service_file` - when enabled on RHEL 7.0 a systemd config will be managed + - `ensure_account` - controls whether `zookeeper` user and group will be ensured (set to `false` to disable this feature) + - `install_method` (default: `package`) - installation method (either `package` or `archive`). `package` will use the available package manager. `archive` will install from an archive file. + - `mirror_url` - Base URL of Apache mirror to use if `install_method` is not `package` + - `archive_checksum` - optional hash to use when verifying installation archive. ex: `{ type => 'sha1', hash => 'abcdef123456' }` and many others, see the `init.pp` file for more details. @@ -252,7 +254,7 @@ If you are versioning your puppet conf with git just add it as submodule, from y ## Dependencies * stdlib `> 2.3.3` - function `ensure_resources` is required - * datacat - experimental (might be removed in future releases) + * archive `>= 0.5.0` - used for tarball installation ## Supported platforms diff --git a/files/znode_exists.sh b/files/znode_exists.sh new file mode 100755 index 0000000..a8e7b97 --- /dev/null +++ b/files/znode_exists.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +function usage () { + echo "usage: $0 znode_path" >&2 + exit 1 +} + +_znode="$1" + +[ -z $_znode ] && usage + +[[ $(echo "stat $_znode" | zkCli.sh 2>&1 >/dev/null) != \ + *'Node does not exist:'* ]] diff --git a/manifests/config.pp b/manifests/config.pp index 9b3f206..8dc658b 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -106,7 +106,8 @@ } } - if $exhibitor_manaaged == 'false' { + if $exhibitor_managed == false { + file { "${cfg_dir}/zoo.cfg": owner => $user, group => $group, diff --git a/manifests/init.pp b/manifests/init.pp index 22a77d5..6180686 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -51,9 +51,10 @@ $peer_type = 'UNSET', $start_with = undef, $ensure_cron = true, - $install_method = package, + $install_method = 'package', $install_dir = '/opt/zookeeper', - $download_url = 'http://mirror.cogentco.com/pub/apache/zookeeper', + $mirror_url = 'http://mirror.cogentco.com/pub/apache', + $archive_checksum = {}, $service_package = undef, $service_name = $::zookeeper::params::service_name, $service_provider = $::zookeeper::params::service_provider, @@ -103,7 +104,8 @@ class { 'zookeeper::install': ensure => $ensure, install_method => $install_method, - download_url => $download_url, + mirror_url => $mirror_url, + archive_checksum => $archive_checksum, install_dir => $install_dir, snap_retain_count => $snap_retain_count, datastore => $datastore, @@ -155,7 +157,7 @@ systemd_unit_after => $systemd_unit_after, } - if ($manage_service) { + if ($manage_service and !$exhibitor_managed) { class { 'zookeeper::service': cfg_dir => $cfg_dir, zoo_dir => $zoo_dir, diff --git a/manifests/install.pp b/manifests/install.pp index 172fe4d..4236818 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -10,9 +10,11 @@ # Should not be included directly # class zookeeper::install( - $install_method = $zookeeper::install_method, - $download_url = 'http://mirror.cogentco.com/pub/apache/zookeeper', + $install_method = 'package', + $mirror_url = 'http://mirror.cogentco.com/pub/apache', + $archive_checksum = {}, $install_dir = '/opt/zookeeper', + $package_dir = '/var/tmp/zookeeper', $ensure = present, $snap_retain_count = 3, $cleanup_sh = '/usr/lib/zookeeper/bin/zkCleanup.sh', @@ -34,6 +36,11 @@ anchor { 'zookeeper::install::end': } if ($install_method == 'package') { + $clean = $manual_clean + $repo_source = is_hash($repo) ? { + true => 'custom', + false => $repo, + } case $::osfamily { 'Debian': { class { 'zookeeper::os::debian': @@ -67,37 +74,82 @@ fail("Module '${module_name}' is not supported on OS: '${::operatingsystem}', family: '${::osfamily}'") } } - } else { + } elsif ($install_method == 'archive') { + include '::archive' + + $basefilename = "zookeeper-${ensure}.tar.gz" + $package_url = "${mirror_url}/zookeeper/zookeeper-${ensure}/${basefilename}" + $extract_path = "${install_dir}-${ensure}" + + if ($manual_clean == undef) { + $clean = versioncmp($ensure, '3.4') ? { + '-1' => true, + default => false, + } + } else { + $clean = $manual_clean + } + package { ['zookeeper','zookeeperd']: ensure => absent } file { $install_dir: ensure => link, - target => "${install_dir}-${ensure}" - } - - exec { 'download-zk-package': - command => "/usr/bin/wget -O /tmp/zookeeper-${ensure}.tar.gz ${package_mirror}/zookeeper-${ensure}/zookeeper-${ensure}.tar.gz", - creates => "/tmp/zookeeper-${ensure}.tar.gz" + target => $extract_path } - exec { 'install-zk-package': - command => "/bin/tar -xvzf /tmp/zookeeper-${ensure}.tar.gz -C /opt", - creates => "${install_dir}-${ensure}/zookeeper-${ensure}.jar", + file { $package_dir: + ensure => directory, + owner => 'zookeeper', + group => 'zookeeper', require => [ - Exec['download-zk-package'] - ] + Group['zookeeper'], + User['zookeeper'], + ], } - - file { "${install_dir}-${ensure}": + + file { $extract_path: ensure => directory, - recurse => true, owner => 'zookeeper', - group => 'zookeeper' + group => 'zookeeper', + require => [ + Group['zookeeper'], + User['zookeeper'], + ], } + + archive { "${package_dir}/${basefilename}": + ensure => present, + extract => true, + extract_command => 'tar xfz %s --strip-components=1', + extract_path => $extract_path, + source => $package_url, + checksum => $archive_checksum['hash'], + checksum_type => $archive_checksum['type'], + creates => "${extract_path}/conf", + cleanup => true, + user => 'zookeeper', + group => 'zookeeper', + require => [ + File[$package_dir], + File[$install_dir], + Group['zookeeper'], + User['zookeeper'], + ], + } + } else { + fail("You must specify a valid install method for zookeeper") } + file { '/usr/local/bin/znode_exists.sh': + ensure => file, + owner => 'root', + group => 'root', + mode => '0755', + source => 'puppet:///modules/zookeeper/znode_exists.sh', + require => File['/usr/local/bin'], + } class { 'zookeeper::post_install': ensure => $ensure, @@ -108,7 +160,7 @@ datastore => $datastore, snap_retain_count => $snap_retain_count, cleanup_sh => $cleanup_sh, - manual_clean => $manual_clean, + manual_clean => $clean, require => Anchor['zookeeper::install::end'], } diff --git a/manifests/service.pp b/manifests/service.pp index f06b6df..68b990a 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -10,7 +10,6 @@ $cfg_dir = '/etc/zookeeper/conf', $service_name = 'zookeeper', $service_ensure = 'running', - $manage_service = true, $manage_service_file = true, $user = 'zookeeper', $group = 'zookeeper', @@ -20,27 +19,26 @@ require ::zookeeper::install - if $manage_service == true { - if $manage_service_file == true { - if $service_provider == 'systemd' { - file { '/usr/lib/systemd/system/zookeeper.service': - ensure => 'present', - content => template('zookeeper/zookeeper.service.erb'), - } ~> - exec { 'systemctl daemon-reload # for zookeeper': - refreshonly => true, - path => $::path, - notify => Service[$service_name] - } - } elsif ( $service_provider == 'init' or $service_provider == 'redhat') { - file {"/etc/init.d/${service_name}": - ensure => present, - content => template('zookeeper/zookeeper.init.erb'), - mode => '0755', - notify => Service[$service_name] - } + if $manage_service_file == true { + if $service_provider == 'systemd' { + file { '/usr/lib/systemd/system/zookeeper.service': + ensure => 'present', + content => template('zookeeper/zookeeper.service.erb'), + } ~> + exec { 'systemctl daemon-reload # for zookeeper': + refreshonly => true, + path => $::path, + notify => Service[$service_name] } - } + } elsif ( $service_provider == 'init' or $service_provider == 'redhat') { + file {"/etc/init.d/${service_name}": + ensure => present, + content => template('zookeeper/zookeeper.init.erb'), + mode => '0755', + notify => Service[$service_name] + } + } + } service { $service_name: ensure => $service_ensure, @@ -57,4 +55,5 @@ File["${cfg_dir}/environment"], File["${cfg_dir}/log4j.properties"], ] } + } diff --git a/manifests/znode.pp b/manifests/znode.pp index 75bf53b..ead4dbd 100644 --- a/manifests/znode.pp +++ b/manifests/znode.pp @@ -1,17 +1,39 @@ define zookeeper::znode( $ensure = '', - $assosiation = '' + $association = '' ) { - + + validate_re($name, '^\/', "znode path must start with a '/'") + if $name =~ /\/\.{1,2}(\/.*)?$/ { + fail("znode name cannot be '.' or '..'") + } + + $create_cmd = shellquote( + '/bin/echo', + "create ${name}", + "\'${association}\'" + ) + + $rm_cmd = shellquote( + '/bin/echo', + "rmr ${name}" + ) + if $ensure == 'present' { exec { "create znode ${name}": - command => "/bin/echo \"create /${name} '${assosiation}'\" | ${zookeeper::install_dir}/bin/zkCli.sh", - unless => "/bin/bash -c \"if [[ \\\"`echo 'ls /' | /opt/zookeeper/bin/zkCli.sh | tail -n2 | head -n1`\\\" == *${name}* ]]; then exit 0; else exit 1; fi\"" + command => "${create_cmd} | zkCli.sh", + unless => shellquote('znode_exists.sh', $name), + path => "/usr/share/zookeeper/bin:${zookeeper::install_dir}/bin:/bin:/usr/bin:/usr/local/bin", + require => Class['::zookeeper::install'], + } } else { exec { "delete znode ${name}": - command => "/bin/echo \"rmr /${name}\" | ${zookeeper::install_dir}/bin/zkCli.sh", - unless => "/bin/bash -c \"if [[ \\\"`echo 'ls /' | /opt/zookeeper/bin/zkCli.sh | tail -n2 | head -n1`\\\" == *${name}* ]]; then exit 0; else exit 1; fi\"" + command => "${rm_cmd} | zkCli.sh", + onlyif => shellquote('znode_exists.sh', $name), + path => "/usr/share/zookeeper/bin:${zookeeper::install_dir}/bin:/bin:/usr/bin:/usr/local/bin", + require => Class['::zookeeper::install'], } } + } diff --git a/metadata.json b/metadata.json index bfe27f5..586b1bc 100644 --- a/metadata.json +++ b/metadata.json @@ -9,6 +9,10 @@ "issues_url": "https://github.com/deric/puppet-zookeeper/issues", "description": "ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.", "dependencies": [ + { + "name": "puppet/archive", + "version_requirement": ">= 0.5.0" + }, { "name": "puppetlabs-stdlib", "version_requirement": ">= 2.3.3 < 5.0.0" diff --git a/spec/classes/config_spec.rb b/spec/classes/config_spec.rb index 22a68b5..6b8a24e 100644 --- a/spec/classes/config_spec.rb +++ b/spec/classes/config_spec.rb @@ -44,7 +44,7 @@ } } it { - should contain_file('/etc/zookeeper/conf/environment').with_content(/ERROR/) + should contain_file("#{cfg_dir}/zookeeper-env.sh").with_content(/ZOOCFGDIR/) } it { @@ -142,7 +142,7 @@ let(:user) { 'zookeeper' } let(:group) { 'zookeeper' } let(:cfg_dir) { '/etc/zookeeper/conf' } - let(:log_dir) { '/var/lib/zookeeper' } + let(:log_dir) { '/var/log/zookeeper' } let(:id_file) { '/etc/zookeeper/conf/myid' } let(:myid) { /1/ } @@ -153,17 +153,17 @@ # set custom params let(:params) { { :id => '2', - :user => 'zoo', - :group => 'zoo', - :cfg_dir => '/var/lib/zookeeper/conf', - :log_dir => '/var/lib/zookeeper/log', + :user => 'zookeeper', + :group => 'zookeeper', + :cfg_dir => '/etc/zookeeper/conf', + :log_dir => '/var/log/zookeeper', } } - let(:user) { 'zoo' } - let(:group) { 'zoo' } - let(:cfg_dir) { '/var/lib/zookeeper/conf' } - let(:log_dir) { '/var/lib/zookeeper/log' } - let(:id_file) { '/var/lib/zookeeper/conf/myid' } + let(:user) { 'zookeeper' } + let(:group) { 'zookeeper' } + let(:cfg_dir) { '/etc/zookeeper/conf' } + let(:log_dir) { '/var/log/zookeeper' } + let(:id_file) { '/etc/zookeeper/conf/myid' } let(:myid) { /2/ } it_behaves_like 'common', 'Debian', 'wheezy' diff --git a/spec/classes/install_spec.rb b/spec/classes/install_spec.rb index f811e90..ea69b93 100644 --- a/spec/classes/install_spec.rb +++ b/spec/classes/install_spec.rb @@ -31,6 +31,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :snap_retain_count => 0, } } @@ -44,6 +45,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :service_package => 'zookeeper-server', } } @@ -57,6 +59,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :packages => [ 'zookeeper', 'zookeeper-bin' ], } } @@ -69,6 +72,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :ensure => 'absent', } } @@ -92,6 +96,7 @@ let(:group) { 'zookeeper' } let(:params) {{ + :install_method => 'package', :snap_retain_count => 1, }} # ENV variable might contain characters which are not supported @@ -166,7 +171,7 @@ 'command' => '/usr/lib/zookeeper/bin/zkCleanup.sh /var/lib/zookeeper 5', 'user' => 'zookeeper', 'hour' => '2', - 'minute' => '42', + 'minute' => '42', }) end end @@ -176,6 +181,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :packages => [ 'zookeeper', 'zookeeper-devel' ], } } @@ -188,6 +194,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :ensure => 'absent', } } @@ -209,6 +216,7 @@ let(:group) { 'zookeeper' } let(:params) { { + :install_method => 'package', :install_java => true, :java_package => 'java-1.7.0-openjdk', } } @@ -275,4 +283,61 @@ end end -end \ No newline at end of file + context 'installing from tar archive' do + let(:user) { 'zookeeper' } + let(:group) { 'zookeeper' } + let(:package_dir) { '/tmp/zookeeper' } + let(:install_dir) { '/opt/zookeeper' } + let(:vers) { '3.4.5' } + let(:mirror_url) { 'http://mirror.cogentco.com/pub/apache' } + let(:basefilename) { "zookeeper-#{vers}.tar.gz" } + let(:package_url) { "#{mirror_url}/zookeeper/zookeeper-#{vers}/zookeeper-#{vers}.tar.gz" } + let(:extract_path) { "#{install_dir}-#{vers}" } + + let(:facts) {{ + :operatingsystem => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + }} + + let(:params) { { + :install_method => 'archive', + :package_dir => package_dir, + :install_dir => install_dir, + :ensure => vers, + :mirror_url => mirror_url, + } } + + it do + should contain_file(package_dir).with({ + :ensure => 'directory', + :owner => user, + :group => group, + }) + end + it do + should contain_file(extract_path).with({ + :ensure => 'directory', + :owner => user, + :group => group, + }) + end + it do + should contain_file(install_dir).with({ + :ensure => 'link', + :target => extract_path, + }) + end + it do + should contain_archive("#{package_dir}/#{basefilename}").with({ + :extract_path => extract_path, + :source => package_url, + :creates => "#{extract_path}/conf", + :user => user, + :group => group, + }) + end + end + + +end diff --git a/spec/classes/service_spec.rb b/spec/classes/service_spec.rb index 09c2b1c..ee08e65 100644 --- a/spec/classes/service_spec.rb +++ b/spec/classes/service_spec.rb @@ -12,7 +12,6 @@ :log_dir => '/var/log/zookeeper', }} - it { should contain_package('zookeeperd') } it { should contain_service('zookeeper').with( :ensure => 'running', :enable => true @@ -38,8 +37,6 @@ :service_provider => 'systemd', }} - it { should contain_package('zookeeper') } - it { should contain_file( '/usr/lib/systemd/system/zookeeper.service' ).with({ diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 95ada8b..d4349b7 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -17,7 +17,7 @@ puppet_module_install(:source => proj_root, :module_name => 'homes') hosts.each do |host| on host, puppet('module','install','puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] } - on host, puppet('module', 'install', 'richardc-datacat'), { :acceptable_exit_codes => [0,1] } + on host, puppet('module', 'install', 'puppet/archive'), { :acceptable_exit_codes => [0,1] } end end -end \ No newline at end of file +end