diff --git a/README.md b/README.md index afbb9a7..80202ad 100644 --- a/README.md +++ b/README.md @@ -1,381 +1,357 @@ # 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 Downloads](http://img.shields.io/puppetforge/dt/deric/zookeeper.svg)](https://forge.puppetlabs.com/deric/zookeeper/scores) 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. ## Requirements * Puppet * Binary or ZooKeeper source code archive Compatibility matrix: | `puppet-zookeeper`| Puppet 3.x | Puppet 4.x | Puppet 5.x | Puppet 6.x | | ----------------- | ------------- |--------------| -----------|----------------| | `0.7.x` | :heavy_check_mark: | :heavy_check_mark: | :question: | :x: | | `0.8.x` | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | | `1.0.x` | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | ## Basic Usage: ```puppet class { 'zookeeper': } ``` ## Cluster setup When running ZooKeeper in the distributed mode each node must have unique ID (`1-255`). The easiest way how to setup multiple ZooKeepers, is by using Hiera. `hiera/host/zk1.example.com.yaml`: ```yaml zookeeper::id: '1' ``` `hiera/host/zk2.example.com.yaml`: ```yaml zookeeper::id: '2' ``` `hiera/host/zk3.example.com.yaml`: ```yaml zookeeper::id: '3' ``` A ZooKeeper quorum should consist of odd number of nodes (usually `3` or `5`). For defining a quorum it is enough to list all IP addresses of all its members. ```puppet class { 'zookeeper': servers => { 1 => '192.168.1.1', 2 => '192.168.1.2', 3 => '192.168.1.3', }, } ``` In case that an array is passed as `servers`, first ZooKeeper will be assigned `ID = 1`. This would produce following configuration: ``` server.1=192.168.1.1:2888:3888 server.2=192.168.1.2:2888:3888 server.3=192.168.1.3:2888:3888 ``` where first port is `election_port` and second one `leader_port`. Both ports could be customized for each ZooKeeper instance. ```puppet class { 'zookeeper': election_port => 2889, leader_port => 3889, servers => { 1 => '192.168.1.1', 2 => '192.168.1.2', 3 => '192.168.1.3', } } ``` ### Observers [Observers](http://zookeeper.apache.org/doc/r3.3.0/zookeeperObservers.html) were introduced in ZooKeeper 3.3.0. To enable this feature simply state which of ZooKeeper servers are observing: ```puppet class { 'zookeeper': servers => ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4', '192.168.1.5'], observers => ['192.168.1.4', '192.168.1.5'] } ``` **Note**: Currently observer server needs to be listed between standard servers (this behavior might change in feature). ### Set binding interface By default ZooKeeper should bind to all interfaces. When you specify `client_ip` only single interface will be used. If `$::ipaddress` is not your public IP (e.g. you are using Docker) make sure to setup correct IP: ```puppet class { 'zookeeper': client_ip => $::ipaddress_eth0 } ``` or in Hiera: ```yaml zookeeper::client_ip: "%{::ipaddress_eth0}" ``` This is a workaround for a a [Facter issue](https://tickets.puppetlabs.com/browse/FACT-380). ### ZooKeeper service Use `service_provider` to override Puppet detection for starting service. ```puppet class { 'zookeeper': service_provider => 'init', manage_service_file => false, } ``` Some reasonable values are: * `init` * `systemd` * `runit` * `exhibitor` - zookeeper process and config will be managed by exhibitor (https://github.com/soabase/exhibitor). Exhibitor is not managed by this module. * `none` - service won't be installed Parameter `manage_service_file` controls whether service definition should be managed by Puppet (default: `false`). Currently supported for `systemd` and `init`. ### Systemd Unit 'After' and 'Want' control By default the module will create the following Unit section in /etc/systemd/system/multi-user.target.wants/zookeeper.service ```` [Unit] Description=Apache ZooKeeper After=network.target ```` Both After and Want (omitted when using the module defaults) can be controled using this module. E.g on CentOS 7 those might have to be configured for 'netwrok-online.target' using the following syntax: ```puppet class { 'zookeeper': systemd_unit_after => 'network-online.target', systemd_unit_want => 'network-online.target', } ``` Which will modify the Unit section to look like: ```` [Unit] Description=Apache ZooKeeper Want=network-online.target 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` - `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) - `global_outstanding_limit` - ZooKeeper will throttle clients so that there is no more than `global_outstanding_limit` outstanding requests in the system. - `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` controls whether ZooKeeper is installed from binary (`package`) or source (`archive`) packages - `archive_version` allows to specify an arbitrary version of ZooKeeper when using source packages - `archive_install_dir` controls the installation directory when using source packages (defaults to `/opt`) - `archive_symlink` controls the name of a version-independent symlink when using source packages - `archive_dl_url` allows to change the download URL for source packages (defaults to apache.org) - `systemd_path` where to put `systemd` service files (applies only if `manage_service_file` and `service_provider == 'systemd'`) - `restart_on_change` whether ZooKeeper service should be restarted on configuration files change (default: `true`) - `remove_host_principal` whether to remove host from Kerberos principal (default: `false`) - `remove_realm_principal` whether to remove relam from Kerberos principal (default: `false`) - `whitelist_4lw` Fine grained control over the set of commands ZooKeeper can execute (an array e.g. `whitelist_4lw = ['*']`) and many others, see the `params.pp` file for more details. If your distribution has multiple packages for ZooKeeper, you can provide all package names as an array. ```puppet class { 'zookeeper': packages => ['zookeeper', 'zookeeper-java'] } ``` ## Logging ZooKeeper uses log4j, following variables can be configured: ```puppet class { 'zookeeper': console_threshold => 'INFO', rollingfile_threshold => 'INFO', tracefile_threshold => 'TRACE', maxfilesize => '256MB', maxbackupindex => 20, } ``` Threshold supported values are: `ALL`, `DEBUG`, `ERROR`, `FATAL`, `INFO`, `OFF`, `TRACE` and `WARN`. [Maxfilesize](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/RollingFileAppender.html#maxFileSize) [MaxBackupIndex](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/RollingFileAppender.html#maxBackupIndex) By default console, rolling file and trace logging can be configured. Additional log appenders (vulgo log methods) can be configured by adding a hash `extra_appenders`. The following sets up syslog logging and points the root logger towards syslog (note that you must have syslog listening on port 514/udp for this to work): ```puppet class { 'zookeeper': log4j_prop => 'INFO,SYSLOG', extra_appenders => { 'Syslog' => { 'class' => 'org.apache.log4j.net.SyslogAppender', 'layout' => 'org.apache.log4j.PatternLayout', 'layout.conversionPattern' => "${hostname} zookeeper[id:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n", 'syslogHost' => 'localhost', 'facility' => 'user', }, }, } ``` ## Hiera Support All parameters could be defined in hiera files, e.g. `common.yaml`, `Debian.yaml` or `zookeeper.yaml`: ```yaml zookeeper::id: 1 zookeeper::client_port: 2181 zookeeper::datastore: '/var/lib/zookeeper' zookeeper::datalogstore: '/disk2/zookeeper' ``` -## Cloudera package - -In Cloudera distribution ZooKeeper package does not provide init scripts (same as in Debian). Package containing init scripts -is called `zookeeper-server` and the service as well. Moreover there's initialization script which should be called after installation. -So, the configuration might look like this: - -```puppet -class { 'zookeeper': - packages => ['zookeeper', 'zookeeper-server'], - service_name => 'zookeeper-server', - initialize_datastore => true -} -``` - -### Managing repository - -For RedHat family currently we support also managing a `cloudera` yum repo versions 4, and 5. It can be enabled with `repo` parameter: - -```puppet -class { 'zookeeper': - repo => 'cloudera', - cdhver => '5', -} -``` - -#### Custom RPM repository +### Custom RPM repository Optionally you can specify a custom repository, using a hash configuration. ```puppet class { 'zookeeper': - cdhver => '5', repo => { - name => 'myrepo', - url => 'http://cusom.url', - descr => 'description' + name => 'myrepo', + url => 'http://custom.url', + descr => 'description' + sslverify => 1, + gpgcheck => true, } } ``` ## Source package Source packages provide the ability to install arbitrary versions of ZooKeeper on any platform. Note that you'll likely have to use the `manage_service_file` in order to be able to control the ZooKeeper service (because source packages do not install service files). ```puppet class { 'zookeeper': install_method => 'archive', archive_version => '3.4.8', } ``` Optionally you can specify a `proxy_server`: ```puppet class { 'zookeeper': install_method => 'archive', archive_version => '3.4.8', proxy_server => 'http://10.0.0.1:8080' } ``` ## Java installation Default: `false` By changing these two parameters you can ensure, that given Java package will be installed before ZooKeeper packages. ```puppet class { 'zookeeper': install_java => true, java_package => 'openjdk-7-jre-headless' } ``` ## Install ### Librarian (recommended) For [puppet-librarian](https://github.com/rodjek/librarian-puppet) just add to `Puppetfile` from Forge: ```ruby mod 'deric-zookeeper' ``` latest (development) version from GitHub ```ruby mod 'deric-zookeeper', git: 'git://github.com/deric/puppet-zookeeper.git' ``` ### submodules If you are versioning your puppet conf with git just add it as submodule, from your repository root: git submodule add git://github.com/deric/puppet-zookeeper.git modules/zookeeper ## Dependencies * stdlib `> 2.3.3` - function `ensure_resources` is required * puppet-archive `> 0.4.4` - provides capabilities to use archives instead of binary packages ## Acceptance testing Fastest way is to run tests on prepared Docker images: ``` BEAKER_set=debian9-6.3 bundle exec rake acceptance ``` For examining system state set Beaker's ENV variable `BEAKER_destroy=no`: ``` BEAKER_destroy=no BEAKER_set=default bundle exec rake acceptance ``` and after finishing tests connect to container: ``` docker exec -it adoring_shirley bash ``` When host machine is NOT provisioned (puppet installed, etc.): ``` PUPPET_install=yes BEAKER_set=debian-8 bundle exec rake acceptance ``` Run on specific OS (see `spec/acceptance/nodesets`), to see available sets: ``` rake beaker:sets ``` ## Supported platforms * Debian/Ubuntu * RedHat/CentOS/Fedora ### Tested on: * Debian (8, 9, 10) * Ubuntu (16.04, 18.04) * RHEL (6, 7) * CentOS (6, 7) * SLES (12) diff --git a/manifests/init.pp b/manifests/init.pp index 2feafa8..d8ce756 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,168 +1,163 @@ # Class: zookeeper # # This module manages ZooKeeper installation # # # Parameters: # * [global_outstanding_limit] Clients can submit requests faster than ZooKeeper can process them, # especially if there are a lot of clients. To prevent ZooKeeper from running out of memory due to # queued requests, ZooKeeper will throttle clients so that there is no more than globalOutstandingLimit # outstanding requests in the system # # # * [whitelist_4lw] Fine grained control over the set of commands ZooKeeper can execute # # whitelist_4lw = ['stat','ruok'] # class zookeeper( # meta options String $ensure = $zookeeper::params::ensure, Variant[Boolean,String] $ensure_account = $zookeeper::params::ensure_account, Boolean $ensure_cron = $zookeeper::params::ensure_cron, String $group = $zookeeper::params::group, Boolean $system_group = $zookeeper::params::system_group, Array[String] $packages = $zookeeper::params::packages, String $shell = $zookeeper::params::shell, String $user = $zookeeper::params::user, Boolean $system_user = $zookeeper::params::system_user, # installation options Hash $archive_checksum = $zookeeper::params::archive_checksum, Optional[String] $archive_dl_site = $zookeeper::params::archive_dl_site, Integer $archive_dl_timeout = $zookeeper::params::archive_dl_timeout, Optional[String] $archive_dl_url = $zookeeper::params::archive_dl_url, String $archive_install_dir = $zookeeper::params::archive_install_dir, Boolean $archive_symlink = $zookeeper::params::archive_symlink, String $archive_symlink_name = $zookeeper::params::archive_symlink_name, String $archive_version = $zookeeper::params::archive_version, Optional[String] $proxy_server = $zookeeper::params::proxy_server, Optional[String] $proxy_type = $zookeeper::params::proxy_type, Optional[String] $cdhver = $zookeeper::params::cdhver, Boolean $install_java = $zookeeper::params::install_java, String $install_method = $zookeeper::params::install_method, String $java_bin = $zookeeper::params::java_bin, String $java_opts = $zookeeper::params::java_opts, Optional[String] $java_package = $zookeeper::params::java_package, - Optional[Variant[String,Hash]] $repo = $zookeeper::params::repo, + Optional[Hash] $repo = $zookeeper::params::repo, # service options Boolean $manage_service = $zookeeper::params::manage_service, Boolean $manage_service_file = $zookeeper::params::manage_service_file, String $pid_dir = $zookeeper::params::pid_dir, Optional[String] $pid_file = $zookeeper::params::pid_file, Boolean $restart_on_change = $zookeeper::params::restart_on_change, String $service_ensure = $zookeeper::params::service_ensure, String $service_name = $zookeeper::params::service_name, Optional[String] $service_provider = $zookeeper::params::service_provider, Optional[String] $systemd_unit_want = $zookeeper::params::systemd_unit_want, String $systemd_unit_after = $zookeeper::params::systemd_unit_after, String $systemd_path = $zookeeper::params::systemd_path, String $zk_dir = $zookeeper::params::zk_dir, # zookeeper config String $cfg_dir = $zookeeper::params::cfg_dir, String $cleanup_sh = $zookeeper::params::cleanup_sh, Optional[String] $client_ip = $zookeeper::params::client_ip, Integer $client_port = $zookeeper::params::client_port, Optional[Integer] $secure_client_port = $zookeeper::params::secure_client_port, Optional[Boolean] $port_unification = $zookeeper::params::port_unification, String $datastore = $zookeeper::params::datastore, Optional[String] $datalogstore = $zookeeper::params::datalogstore, Integer $election_port = $zookeeper::params::election_port, String $export_tag = $zookeeper::params::export_tag, String $id = $zookeeper::params::id, Integer $init_limit = $zookeeper::params::init_limit, Boolean $initialize_datastore = $zookeeper::params::initialize_datastore, String $initialize_datastore_bin = $zookeeper::params::initialize_datastore_bin, Boolean $leader = $zookeeper::params::leader, Integer $leader_port = $zookeeper::params::leader_port, String $log_dir = $zookeeper::params::log_dir, Boolean $manual_clean = $zookeeper::params::manual_clean, Optional[Integer] $max_session_timeout = $zookeeper::params::max_session_timeout, Optional[Integer] $min_session_timeout = $zookeeper::params::min_session_timeout, Array[String] $observers = $zookeeper::params::observers, Integer $purge_interval = $zookeeper::params::purge_interval, Variant[Array[String],Hash[String,String]] $servers = $zookeeper::params::servers, Integer $pre_alloc_size = $zookeeper::params::pre_alloc_size, Integer $snap_count = $zookeeper::params::snap_count, Integer $snap_retain_count = $zookeeper::params::snap_retain_count, Integer $sync_limit = $zookeeper::params::sync_limit, Integer $tick_time = $zookeeper::params::tick_time, Integer $global_outstanding_limit = $zookeeper::params::global_outstanding_limit, Boolean $use_sasl_auth = $zookeeper::params::use_sasl_auth, String $zoo_dir = $zookeeper::params::zoo_dir, String $zoo_main = $zookeeper::params::zoo_main, Boolean $quorum_listen_on_all_ips = $zookeeper::params::quorum_listen_on_all_ips, # log4j properties String $environment_file = $zookeeper::params::environment_file, String $log4j_prop = $zookeeper::params::log4j_prop, String $maxfilesize = $zookeeper::params::maxfilesize, Integer $maxbackupindex = $zookeeper::params::maxbackupindex, Optional[Integer] $max_allowed_connections = $zookeeper::params::max_allowed_connections, String $peer_type = $zookeeper::params::peer_type, String $rollingfile_threshold = $zookeeper::params::rollingfile_threshold, String $tracefile_threshold = $zookeeper::params::tracefile_threshold, String $console_threshold = $zookeeper::params::console_threshold, Hash[String,Hash[String,String]] $extra_appenders = $zookeeper::params::extra_appenders, # sasl options Hash[String, String] $sasl_users = $zookeeper::params::sasl_users, String $keytab_path = $zookeeper::params::keytab_path, String $principal = $zookeeper::params::principal, String $realm = $zookeeper::params::realm, Boolean $sasl_krb5 = $zookeeper::params::sasl_krb5, Boolean $store_key = $zookeeper::params::store_key, Boolean $use_keytab = $zookeeper::params::use_keytab, Boolean $use_ticket_cache = $zookeeper::params::use_ticket_cache, Boolean $remove_host_principal = $zookeeper::params::remove_host_principal, Boolean $remove_realm_principal = $zookeeper::params::remove_realm_principal, # four letter words whitelist Array[String] $whitelist_4lw = $zookeeper::params::whitelist_4lw, ) inherits ::zookeeper::params { if $pid_file { $pid_path = $pid_file } else { $pid_path = "${pid_dir}/zookeeper.pid" } - $repo_source = is_hash($repo) ? { - true => 'custom', - false => $repo - } - if $zookeeper::ensure_account { group { $group: ensure => $ensure_account, system => $system_group, } user { $user: ensure => $ensure_account, home => $datastore, comment => 'Zookeeper', gid => $group, shell => $shell, system => $system_user, require => Group[$group], } } include zookeeper::install include zookeeper::config anchor { 'zookeeper::start': } -> Class['zookeeper::install'] -> Class['zookeeper::config'] if ($use_sasl_auth) { include zookeeper::sasl Class['zookeeper::config'] -> Class['zookeeper::sasl'] -> Class['zookeeper::service'] } if ($manage_service) and ($service_provider != 'exhibitor') { include zookeeper::service Class['zookeeper::config'] -> Class['zookeeper::service'] -> Anchor['zookeeper::end'] } anchor { 'zookeeper::end': } } diff --git a/manifests/install/repo.pp b/manifests/install/repo.pp index 09f9f48..1b05562 100644 --- a/manifests/install/repo.pp +++ b/manifests/install/repo.pp @@ -1,104 +1,36 @@ # == Class zookeeper::install::repo # # This class manages yum repository for Zookeeper packages # # PRIVATE CLASS - do not use directly (use main `zookeeper` class). class zookeeper::install::repo inherits zookeeper::install { - if $facts['os']['family'] == 'RedHat' { - $os_name = downcase($facts['os']['family']) - } else { - $os_name = downcase($facts['os']['name']) - } - $os_release = $facts['os']['release']['major'] - $os_hardware = $facts['os']['hardware'] - - if $zookeeper::repo_source { - case $zookeeper::repo_source { - undef: {} # nothing to do - 'cloudera': { - if $zookeeper::cdhver == undef { - fail('Cloudera repo is required, but no CDH version is provided.') - } - case $zookeeper::cdhver { - '4': { - case $os_hardware { - 'i386', 'x86_64': { - case $os_release { - '6', '7': { - $release = '6' - } - default: { - fail("Yum repository '${zookeeper::repo_source}' is not supported for ${os_name} version ${os_release}") - } - } - } - default: { - fail("Yum repository '${zookeeper::repo_source}' is not supported for architecture ${os_hardware}") - } - } - } - '5': { - case $os_hardware { - 'x86_64': { - case $os_release { # CentOS uses os_release=2015 - '6', '7', '12', '2015': { - $release = $os_release - } - default: { - fail("Yum repository '${zookeeper::repo_source}' is not supported for ${os_name} version ${os_release}") - } - } - } - default: { - fail("Yum repository '${zookeeper::repo_source}' is not supported for architecture ${os_hardware}") - } - } - } - default: { - fail("CDH version'${zookeeper::cdhver}' is not a supported cloudera repo.") - } - } - # Puppet 4 compatibility: force variable to be a String - yumrepo { "cloudera-cdh${zookeeper::cdhver}": - ensure => $zookeeper::ensure, - descr => "Cloudera's Distribution for Hadoop, Version ${zookeeper::cdhver}", - baseurl => "http://archive.cloudera.com/cdh${zookeeper::cdhver}/${os_name}/${release}/${os_hardware}/cdh/${zookeeper::cdhver}/", - gpgkey => "http://archive.cloudera.com/cdh${zookeeper::cdhver}/${os_name}/${release}/${os_hardware}/cdh/RPM-GPG-KEY-cloudera", - gpgcheck => 1, - } - } - 'custom':{ + if $zookeeper::repo { + case $facts['os']['family']{ + 'RedHat', 'Suse': { $_config = $zookeeper::repo validate_hash($_config) if $_config['name'] == undef or $_config['url'] == undef or $_config['descr'] == undef { fail('Invalid parameter settings for custom repo') } - case $os_release { - '6', '7', '12': { - # Puppet 4 compatibility: force variable to be a String - yumrepo { $_config['name']: - ensure => $zookeeper::ensure, - descr => $_config['descr'], - baseurl => $_config['url'], - enabled => 1, - sslverify => empty($_config['sslverify']) ? { - true => 0, - false => $_config['sslverify'] - }, - gpgcheck => empty($_config['gpgcheck']) ? { - true => 0, - false => $_config['gpgcheck'] - }, - } - } - default: { - fail("${facts['os']['family']} '${os_release}' is not a supported.") - } + # Puppet 4 compatibility: force variable to be a String + yumrepo { $_config['name']: + ensure => $zookeeper::ensure, + descr => $_config['descr'], + baseurl => $_config['url'], + enabled => 1, + sslverify => empty($_config['sslverify']) ? { + true => 0, + false => $_config['sslverify'] + }, + gpgcheck => empty($_config['gpgcheck']) ? { + true => 0, + false => $_config['gpgcheck'] + }, } } default: { - fail("\"${module_name}\" provides no repository information for yum repository \"${zookeeper::repo_source}\"") + fail("\"${module_name}\" doesn't support repository for ${facts['os']['family']} yet.") } } } } diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 04fa081..9f338c7 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,283 +1,270 @@ require 'spec_helper' shared_examples 'zookeeper' do |os_facts| let(:user) { 'zookeeper' } let(:group) { 'zookeeper' } os_info = get_os_info(os_facts) service_name = os_info[:service_name] environment_file = os_info[:environment_file] init_provider = os_info[:init_provider] should_install_zookeeperd = os_info[:should_install_zookeeperd] it { is_expected.to contain_class('zookeeper::config') } it { is_expected.to contain_class('zookeeper::install') } it { is_expected.to contain_class('zookeeper::service') } it { is_expected.to compile.with_all_deps } it { is_expected.to contain_service(service_name) } it { is_expected.to contain_service(service_name).that_subscribes_to('File[/etc/zookeeper/conf/myid]') } it { is_expected.to contain_service(service_name).that_subscribes_to('File[/etc/zookeeper/conf/zoo.cfg]') } it { is_expected.to contain_service(service_name).that_subscribes_to("File[#{environment_file}]") } it { is_expected.to contain_service(service_name).that_subscribes_to('File[/etc/zookeeper/conf/log4j.properties]') } context 'skip service restart' do let(:params) do { restart_on_change: false, } end it { is_expected.to contain_service(service_name) } it { is_expected.not_to contain_service(service_name).that_subscribes_to('File[/etc/zookeeper/conf/myid]') } it { is_expected.not_to contain_service(service_name).that_subscribes_to('File[/etc/zookeeper/conf/zoo.cfg]') } it { is_expected.not_to contain_service(service_name).that_subscribes_to("File[#{environment_file}]") } it { is_expected.not_to contain_service(service_name).that_subscribes_to('File[/etc/zookeeper/conf/log4j.properties]') } end context 'allow installing multiple packages' do let(:params) do { packages: ['zookeeper', 'zookeeper-bin'], } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_package('zookeeper').with(ensure: 'present') } it { is_expected.to contain_package('zookeeper-bin').with(ensure: 'present') } it { is_expected.to contain_service(service_name).with(ensure: 'running') } # datastore exec is not included by default it { is_expected.not_to contain_exec('initialize_datastore') } it { is_expected.to contain_user('zookeeper').with(ensure: 'present') } it { is_expected.to contain_group('zookeeper').with(ensure: 'present') } end context 'Cloudera packaging' do let(:params) do { packages: ['zookeeper', 'zookeeper-server'], service_name: 'zookeeper-server', initialize_datastore: true, } end it { is_expected.to contain_package('zookeeper').with(ensure: 'present') } it { is_expected.to contain_package('zookeeper-server').with(ensure: 'present') } it { is_expected.to contain_service('zookeeper-server').with(ensure: 'running') } it { is_expected.to contain_exec('initialize_datastore') } end context 'setting minSessionTimeout' do let(:params) do { min_session_timeout: 3000, } end it do is_expected.to contain_file( '/etc/zookeeper/conf/zoo.cfg', ).with_content(%r{minSessionTimeout=3000}) end end context 'setting maxSessionTimeout' do let(:params) do { max_session_timeout: 60_000, } end it do is_expected.to contain_file( '/etc/zookeeper/conf/zoo.cfg', ).with_content(%r{maxSessionTimeout=60000}) end end context 'disable service management' do let(:params) do { manage_service: false, } end it { is_expected.to contain_package('zookeeper').with(ensure: 'present') } it { is_expected.not_to contain_service(service_name).with(ensure: 'running') } it { is_expected.not_to contain_class('zookeeper::service') } end if %r{RedHat|Suse}.match?(os_facts[:os]['family']) context 'Do not use cloudera by default' do it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('zookeeper::install::repo') } it { is_expected.not_to contain_yumrepo('cloudera-cdh5') } end - if os_facts[:os]['release']['major'].to_i < 7 - context 'use Cloudera RPM repo' do - let(:params) do - { - repo: 'cloudera', - cdhver: '5', - } - end - - it { is_expected.to compile.with_all_deps } - it { is_expected.to contain_class('zookeeper::install::repo') } - - it { is_expected.to contain_yumrepo('cloudera-cdh5') } - - context 'custom RPM repo' do - let(:params) do - { - repo: { - 'name' => 'myrepo', - 'url' => 'http://repo.url', - 'descr' => 'custom repo', - }, - cdhver: '5', - } - end - - it { is_expected.to contain_yumrepo('myrepo').with(baseurl: 'http://repo.url') } - end + context 'custom RPM repo' do + let(:params) do + { + repo: { + 'name' => 'myrepo', + 'url' => 'http://repo.url', + 'descr' => 'custom repo', + }, + cdhver: '5', + } end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('zookeeper::install::repo') } + + it { is_expected.to contain_yumrepo('myrepo').with(baseurl: 'http://repo.url') } end end context 'service provider' do context 'autodetect provider' do it { is_expected.to contain_package('zookeeper').with(ensure: 'present') } if %r{RedHat|Suse}.match?(os_facts[:os]['family']) it { is_expected.to contain_package('zookeeper-server').with(ensure: 'present') } else it { is_expected.not_to contain_package('zookeeper-server').with(ensure: 'present') } end it do is_expected.to contain_service(service_name).with(ensure: 'running', provider: init_provider) end end it { is_expected.to contain_class('zookeeper::service') } end context 'allow passing specific version' do let(:version) { '3.4.5+dfsg-1' } let(:params) do { ensure: version, } end it { is_expected.to contain_package('zookeeper').with(ensure: version) } if should_install_zookeeperd it { is_expected.to contain_package('zookeeperd').with(ensure: version) } else it { is_expected.not_to contain_package('zookeeperd').with(ensure: version) } end it { is_expected.to contain_user('zookeeper').with(ensure: 'present') } end context 'set pid file for init provider' do let(:params) do { zoo_dir: '/usr/lib/zookeeper', log_dir: '/var/log/zookeeper', manage_service: true, manage_service_file: true, service_provider: 'init', } end it do is_expected.to contain_file( '/etc/zookeeper/conf/log4j.properties', ).with_content(%r{zookeeper.log.dir=/var/log/zookeeper}) end context 'set service provider' do it { is_expected.to contain_package('zookeeper').with(ensure: 'present') } it do is_expected.to contain_service(service_name).with(ensure: 'running', provider: 'init') end end if %r{RedHat|Suse}.match?(os_facts[:os]['family']) it do is_expected.to contain_file( "/etc/init.d/#{service_name}", ).with_content(%r{pidfile=/var/run/zookeeper.pid}) end else it do is_expected.to contain_file( environment_file, ).with_content(%r{PIDFILE=/var/run/zookeeper.pid}) end end end context 'create env file' do it do is_expected.to contain_file( environment_file, ) end end context 'managed by exhibitor' do let(:params) do { service_provider: 'exhibitor', service_name: 'zookeeper', cfg_dir: '/opt/zookeeper/conf', } end it { is_expected.not_to contain_class('zookeeper::service') } it { is_expected.not_to contain_service(service_name) } it { is_expected.not_to contain_file('/opt/zookeeper/conf/zoo.cfg') } it { is_expected.not_to contain_file('/opt/zookeeper/conf/myid') } end context 'install from archive' do let(:params) do { install_method: 'archive', archive_version: '3.4.9', } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('Zookeeper::Install::Archive') } it { is_expected.not_to contain_package('zookeeper').with(ensure: 'present') } it { is_expected.to contain_service(service_name).with(ensure: 'running') } it { is_expected.to contain_user('zookeeper').with(ensure: 'present') } it { is_expected.to contain_group('zookeeper').with(ensure: 'present') } end end describe 'zookeeper', type: :class do on_supported_os.each do |os, os_facts| os_facts[:os]['hardware'] = 'x86_64' context "on #{os}" do let(:facts) do os_facts.merge(ipaddress: '192.168.1.1') end include_examples 'zookeeper', os_facts end end end diff --git a/spec/classes/repo_spec.rb b/spec/classes/repo_spec.rb index ac21c94..bacbb8c 100644 --- a/spec/classes/repo_spec.rb +++ b/spec/classes/repo_spec.rb @@ -1,160 +1,115 @@ require 'spec_helper' shared_examples 'zookeeper repo release support' do |os_facts| - os_name = if os_facts[:os]['family'] == 'RedHat' - os_facts[:os]['family'].downcase - else - os_facts[:os]['name'].downcase - end - os_release = os_facts[:os]['release']['major'] - context 'fail when release not supported' do let :pre_condition do 'class {"zookeeper": - repo => "cloudera", - cdhver => "5", + repo => { + name => "myrepo", + url => "http://custom.url", + descr => "description", + } }' end it do expect { is_expected.to compile - }.to raise_error(%r{is not supported for #{os_name} version #{os_release}}) - end - end -end - -shared_examples 'zookeeper repo arch support' do |os_facts| - os_hardware = os_facts[:os]['hardware'] - - context 'fail when architecture not supported' do - let :pre_condition do - 'class {"zookeeper": - repo => "cloudera", - cdhver => "5", - }' - end - - it do - expect { - is_expected.to compile - }.to raise_error(%r{is not supported for architecture #{os_hardware}}) + }.to raise_error(%r{support repository for #{os_facts[:os]['family']}}) end end end shared_examples 'zookeeper repo' do |os_facts| let(:user) { 'zookeeper' } let(:group) { 'zookeeper' } - os_name = if os_facts[:os]['family'] == 'RedHat' - os_facts[:os]['family'].downcase - else - os_facts[:os]['name'].downcase - end - os_release = os_facts[:os]['release']['major'] - os_hardware = os_facts[:os]['hardware'] - if %r{RedHat|Suse}.match?(os_facts[:os]['family']) context 'Cloudera repo' do let :pre_condition do 'class {"zookeeper": - repo => "cloudera", - cdhver => "5", + repo => { + name => "myrepo", + url => "http://custom.url", + descr => "description", + } }' end - if (os_facts[:os]['family'] == 'RedHat') && (os_release.to_i < 8) - it do - is_expected.to contain_yumrepo('cloudera-cdh5').with(baseurl: "http://archive.cloudera.com/cdh5/#{os_name}/#{os_release}/#{os_hardware}/cdh/5/") - end + it do + is_expected.to contain_yumrepo('myrepo').with(baseurl: 'http://custom.url') end end end - context 'fail when CDH version not supported' do - let :pre_condition do - 'class {"zookeeper": - repo => "cloudera", - cdhver => "6", - }' - end - - it do - expect { - is_expected.to compile - }.to raise_error(%r{is not a supported cloudera repo.}) - end - end - context 'fail when repository source not supported' do let :pre_condition do 'class {"zookeeper": repo => "another-repo", }' end - it do + it 'requires repo to be a Hash (or not defined)' do expect { is_expected.to compile - }.to raise_error(%r{provides no repository information for yum repository}) + }.to raise_error(%r{type Undef or Hash}) end end end describe 'zookeeper::install::repo' do on_supported_os.each do |os, os_facts| os_facts[:os]['hardware'] = 'x86_64' context "on #{os}" do let(:facts) do os_facts.merge(ipaddress: '192.168.1.1') end include_examples 'zookeeper repo', os_facts end end context 'test unsupported repo arch' do test_on = { hardwaremodels: ['arc'], supported_os: [ { 'operatingsystem' => 'RedHat', 'operatingsystemrelease' => ['7'], }, ], } on_supported_os(test_on).each do |os, os_facts| context "on #{os}" do let(:facts) do os_facts.merge(ipaddress: '192.168.1.1') end include_examples 'zookeeper repo arch support', os_facts end end end context 'test unsupported repo release' do test_on = { supported_os: [ { - 'operatingsystem' => 'RedHat', - 'operatingsystemrelease' => ['8'], + 'operatingsystem' => 'Debian', + 'operatingsystemrelease' => ['10'], }, ], } on_supported_os(test_on).each do |os, os_facts| os_facts[:os]['hardware'] = 'x86_64' context "on #{os}" do let(:facts) do os_facts.merge(ipaddress: '192.168.1.1') end include_examples 'zookeeper repo release support', os_facts end end end end