├── .gitignore ├── spec ├── spec_helper.rb ├── defines │ └── template_spec.rb └── classes │ └── elasticsearch_init_spec.rb ├── .fixtures.yml ├── templates └── etc │ ├── default │ └── elasticsearch.erb │ └── elasticsearch │ └── elasticsearch.yml.erb ├── .gemfile ├── Rakefile ├── Modulefile ├── CONTRIBUTORS ├── LICENSE ├── .travis.yml ├── manifests ├── python.pp ├── java.pp ├── config.pp ├── package.pp ├── plugin.pp ├── params.pp ├── template.pp ├── service.pp └── init.pp ├── CONTRIBUTING.md ├── CHANGELOG └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | Gemfile.lock 3 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'puppetlabs_spec_helper/module_spec_helper' 3 | -------------------------------------------------------------------------------- /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | repositories: 3 | stdlib: git://github.com/puppetlabs/puppetlabs-stdlib.git 4 | symlinks: 5 | elasticsearch: "#{source_dir}" 6 | -------------------------------------------------------------------------------- /templates/etc/default/elasticsearch.erb: -------------------------------------------------------------------------------- 1 | ### MANAGED BY PUPPET ### 2 | 3 | <% scope.lookupvar('elasticsearch::service_settings').sort.map do |key, value| -%> 4 | <%= key %>=<%= value %> 5 | <% end -%> 6 | -------------------------------------------------------------------------------- /.gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | puppetversion = ENV['PUPPET_VERSION'] 4 | gem 'puppet', puppetversion, :require => false 5 | gem 'puppet-lint' 6 | gem 'rspec-puppet' 7 | gem 'puppetlabs_spec_helper', '>= 0.1.0' 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'puppetlabs_spec_helper/rake_tasks' 3 | require 'puppet-lint' 4 | PuppetLint.configuration.send("disable_80chars") 5 | PuppetLint.configuration.send("disable_class_inherits_from_params_class") 6 | -------------------------------------------------------------------------------- /Modulefile: -------------------------------------------------------------------------------- 1 | name 'ispavailability-elasticsearch' 2 | version '0.1.3' 3 | source 'https://github.com/elasticsearch/puppet-elasticsearch' 4 | author 'ispavailability' 5 | license 'Apache License, Version 2.0' 6 | summary 'Module for managing and configuring Elasticsearch nodes' 7 | description 'Module for managing and configuring Elasticsearch nodes' 8 | project_page 'https://github.com/elasticsearch/puppet-elasticsearch' 9 | dependency 'puppetlabs/stdlib', '>= 3.0.0' 10 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | The following is a list of people who have contributed ideas, code, bug 2 | reports, or in general have helped this puppet module along its way. 3 | 4 | Project Owner 5 | * Richard Pijnenburg (electrical) 6 | 7 | Contributors: 8 | Martin Seener (martinseener) 9 | Marcus Furlong (furlongm) 10 | Chris Boulton (chrisboulton) 11 | Igor Galić (igalic) 12 | Vincent Janelle (vjanelle) 13 | Mathieu Bornoz (mbornoz) 14 | Justin Lambert (jlambert121) 15 | Brian Lalor (blalor) 16 | Stas Alekseev (salekseev) 17 | Simon Effenberg (Savar) 18 | Bruce Morrison (brucem) 19 | deanmalmgren 20 | Matteo Sessa (msessa-cotd) 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012-2013 Richard Pijnenburg 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 1.8.7 4 | - 1.9.3 5 | - ruby-head 6 | script: 7 | - "rake lint" 8 | - "rake spec SPEC_OPTS='--format documentation'" 9 | env: 10 | - PUPPET_VERSION="~> 2.7.0" 11 | - PUPPET_VERSION="~> 3.0.0" 12 | - PUPPET_VERSION="~> 3.1.0" 13 | - PUPPET_VERSION="~> 3.2.0" 14 | matrix: 15 | allow_failures: 16 | - rvm: ruby-head 17 | exclude: 18 | - rvm: 1.9.3 19 | env: PUPPET_GEM_VERSION="~> 2.7.0" 20 | - rvm: ruby-head 21 | env: PUPPET_GEM_VERSION="~> 2.7.0" 22 | gemfile: .gemfile 23 | notifications: 24 | email: 25 | - richard@ispavailability.com 26 | -------------------------------------------------------------------------------- /manifests/python.pp: -------------------------------------------------------------------------------- 1 | # there are many python bindings for elasticsearch. This provides all 2 | # the ones we know about http://www.elasticsearch.org/guide/clients/ 3 | define elasticsearch::python ( 4 | $ensure = 'installed', 5 | ) { 6 | 7 | # make sure the package name is valid and setup the provider as 8 | # necessary 9 | case $name { 10 | 'pyes': { 11 | $provider = 'pip' 12 | } 13 | 'rawes': { 14 | $provider = 'pip' 15 | } 16 | 'pyelasticsearch': { 17 | $provider = 'pip' 18 | } 19 | 'ESClient': { 20 | $provider = 'pip' 21 | } 22 | 'elasticutils': { 23 | $provider = 'pip' 24 | } 25 | default: { 26 | fail("unknown python binding package '${name}'") 27 | } 28 | } 29 | 30 | package { $name: 31 | ensure => $ensure, 32 | provider => $provider, 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /manifests/java.pp: -------------------------------------------------------------------------------- 1 | # == Class: elasticsearch::java 2 | # 3 | # This class exists to install java if its not managed from an other module 4 | # 5 | # 6 | # === Parameters 7 | # 8 | # This class does not provide any parameters. 9 | # 10 | # 11 | # === Examples 12 | # 13 | # This class may be imported by other classes to use its functionality: 14 | # class { 'elasticsearch::java': } 15 | # 16 | # It is not intended to be used directly by external resources like node 17 | # definitions or other modules. 18 | # 19 | # 20 | # === Authors 21 | # 22 | # * Richard Pijnenburg 23 | # 24 | class elasticsearch::java { 25 | 26 | if $elasticsearch::java_package == undef { 27 | # Default Java package 28 | case $::operatingsystem { 29 | 'CentOS', 'Fedora', 'Scientific', 'RedHat', 'Amazon', 'OracleLinux': { 30 | $package = 'java-1.6.0-openjdk' 31 | } 32 | 'Debian', 'Ubuntu': { 33 | $package = 'openjdk-6-jre-headless' 34 | } 35 | default: { 36 | fail("\"${module_name}\" provides no java package 37 | for \"${::operatingsystem}\"") 38 | } 39 | } 40 | } else { 41 | $package = $elasticsearch::java_package 42 | } 43 | 44 | ## Install the java package unless already specified somewhere else 45 | if !defined(Package[$package]) { 46 | package { $package: 47 | ensure => present 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /manifests/config.pp: -------------------------------------------------------------------------------- 1 | # == Class: elasticsearch::config 2 | # 3 | # This class exists to coordinate all configuration related actions, 4 | # functionality and logical units in a central place. 5 | # 6 | # 7 | # === Parameters 8 | # 9 | # This class does not provide any parameters. 10 | # 11 | # 12 | # === Examples 13 | # 14 | # This class may be imported by other classes to use its functionality: 15 | # class { 'elasticsearch::config': } 16 | # 17 | # It is not intended to be used directly by external resources like node 18 | # definitions or other modules. 19 | # 20 | # 21 | # === Authors 22 | # 23 | # * Richard Pijnenburg 24 | # 25 | class elasticsearch::config { 26 | 27 | include elasticsearch 28 | 29 | Exec { 30 | path => [ '/bin', '/usr/bin', '/usr/local/bin' ], 31 | cwd => '/', 32 | } 33 | 34 | $settings = $elasticsearch::config 35 | 36 | $notify_elasticsearch = $elasticsearch::restart_on_change ? { 37 | false => undef, 38 | default => Class['elasticsearch::service'], 39 | 40 | } 41 | 42 | file { $elasticsearch::confdir: 43 | ensure => directory, 44 | owner => 'root', 45 | group => 'root', 46 | mode => '0644', 47 | } 48 | 49 | file { "${elasticsearch::confdir}/elasticsearch.yml": 50 | ensure => file, 51 | content => template("${module_name}/etc/elasticsearch/elasticsearch.yml.erb"), 52 | owner => 'root', 53 | group => 'root', 54 | mode => '0644', 55 | require => [ Class['elasticsearch::package'], File[$elasticsearch::confdir] ], 56 | notify => $notify_elasticsearch, 57 | } 58 | 59 | exec { 'mkdir_templates': 60 | command => "mkdir -p ${elasticsearch::confdir}/templates_import", 61 | creates => "${elasticsearch::confdir}/templates_import" 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | If you have a bugfix or new feature that you would like to contribute to this puppet module, please find or open an issue about it first. Talk about what you would like to do. It may be that somebody is already working on it, or that there are particular issues that you should know about before implementing the change. 2 | 3 | We enjoy working with contributors to get their code accepted. There are many approaches to fixing a problem and it is important to find the best approach before writing too much code. 4 | 5 | The process for contributing to any of the Elasticsearch repositories is similar. 6 | 7 | 1. Sign the contributor license agreement 8 | Please make sure you have signed the [Contributor License Agreement](http://www.elasticsearch.org/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once. 9 | 10 | 2. Run the rspec tests and ensure it completes without errors with your changes. 11 | 12 | 3. Rebase your changes 13 | Update your local repository with the most recent code from the main this puppet module repository, and rebase your branch on top of the latest master branch. We prefer your changes to be squashed into a single commit. 14 | 15 | 4. Submit a pull request 16 | Push your local changes to your forked copy of the repository and submit a pull request. In the pull request, describe what your changes do and mention the number of the issue where discussion has taken place, eg “Closes #123″. 17 | 18 | Then sit back and wait. There will probably be discussion about the pull request and, if any changes are needed, we would love to work with you to get your pull request merged into this puppet module. 19 | -------------------------------------------------------------------------------- /manifests/package.pp: -------------------------------------------------------------------------------- 1 | # == Class: elasticsearch::package 2 | # 3 | # This class exists to coordinate all software package management related 4 | # actions, functionality and logical units in a central place. 5 | # 6 | # 7 | # === Parameters 8 | # 9 | # This class does not provide any parameters. 10 | # 11 | # 12 | # === Examples 13 | # 14 | # This class may be imported by other classes to use its functionality: 15 | # class { 'elasticsearch::package': } 16 | # 17 | # It is not intended to be used directly by external resources like node 18 | # definitions or other modules. 19 | # 20 | # 21 | # === Authors 22 | # 23 | # * Richard Pijnenburg 24 | # 25 | class elasticsearch::package { 26 | 27 | #### Package management 28 | 29 | # set params: in operation 30 | if $elasticsearch::ensure == 'present' { 31 | 32 | if $elasticsearch::version == false { 33 | 34 | $package_ensure = $elasticsearch::autoupgrade ? { 35 | true => 'latest', 36 | default => 'present', 37 | } 38 | 39 | } else { 40 | 41 | $package_ensure = $elasticsearch::version 42 | 43 | } 44 | 45 | # set params: removal 46 | } else { 47 | $package_ensure = 'purged' 48 | } 49 | 50 | if $elasticsearch::pkg_source { 51 | 52 | $filenameArray = split($elasticsearch::pkg_source, '/') 53 | $basefilename = $filenameArray[-1] 54 | 55 | $extArray = split($basefilename, '\.') 56 | $ext = $extArray[-1] 57 | 58 | $tmpSource = "/tmp/${basefilename}" 59 | 60 | file { $tmpSource: 61 | source => $elasticsearch::pkg_source, 62 | owner => 'root', 63 | group => 'root', 64 | backup => false 65 | } 66 | 67 | case $ext { 68 | 'deb': { $pkg_provider = 'dpkg' } 69 | 'rpm': { $pkg_provider = 'rpm' } 70 | default: { fail("Unknown file extention \"${ext}\"") } 71 | } 72 | } else { 73 | $tmpSource = undef 74 | $pkg_provider = undef 75 | } 76 | 77 | # action 78 | package { $elasticsearch::params::package: 79 | ensure => $package_ensure, 80 | source => $tmpSource, 81 | provider => $pkg_provider 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /templates/etc/elasticsearch/elasticsearch.yml.erb: -------------------------------------------------------------------------------- 1 | <%- 2 | 3 | # Function to make a structured and sorted yaml representation out of a hash 4 | def recursive_hash_to_yml_string(hash, depth=0) 5 | spacer = "" 6 | depth.times { spacer += " "} 7 | hash.keys.sort.each do |sorted_key| 8 | @yml_string += spacer + sorted_key + ": " 9 | if hash[sorted_key].is_a?(Array) 10 | keyspacer = "" 11 | sorted_key.length.times { keyspacer += " " } 12 | @yml_string += "\n" 13 | hash[sorted_key].each do |item| 14 | @yml_string += spacer + keyspacer + "- " + item +"\n" 15 | end 16 | elsif hash[sorted_key].is_a?(Hash) 17 | @yml_string += "\n" 18 | recursive_hash_to_yml_string(hash[sorted_key], depth+1) 19 | else 20 | @yml_string += "#{hash[sorted_key].to_s}\n" 21 | end 22 | end 23 | end 24 | 25 | # Function to transform shorted write up of the keys into full hash representation 26 | def transform(hash) 27 | return_vals = [] 28 | 29 | hash.each do |key,val| 30 | if m = /^([^.]+)\.(.*)$/.match(key) 31 | temp = { m[1] => { m[2] => val } } 32 | transform(temp).each do |stuff| 33 | return_vals << stuff 34 | end 35 | else 36 | if val.is_a?(Hash) 37 | transform(val).each do |stuff| 38 | return_vals << { key => stuff } 39 | end 40 | else 41 | return_vals << { key => val } 42 | end 43 | end 44 | end 45 | 46 | return_vals 47 | end 48 | 49 | # Function to deep merge hashes with same keys 50 | class ::Hash 51 | def deep_merge_with_array_values_concatenated(hash) 52 | target = dup 53 | 54 | hash.keys.each do |key| 55 | if hash[key].is_a? Hash and self[key].is_a? Hash 56 | target[key] = target[key].deep_merge_with_array_values_concatenated(hash[key]) 57 | next 58 | end 59 | 60 | if hash[key].is_a?(Array) && target[key].is_a?(Array) 61 | target[key] = target[key] + hash[key] 62 | else 63 | target[key] = hash[key] 64 | end 65 | end 66 | 67 | target 68 | end 69 | end 70 | 71 | # initial string 72 | @yml_string = "### MANAGED BY PUPPET ###\n" 73 | 74 | if !@settings.empty? 75 | 76 | @yml_string += "---\n" 77 | 78 | ## Transform shorted keys into full write up 79 | transformed_config = transform(@settings) 80 | 81 | # Merge it back into a hash 82 | tmphash = { } 83 | transformed_config.each do |subhash| 84 | tmphash = tmphash.deep_merge_with_array_values_concatenated(subhash) 85 | end 86 | 87 | # Transform it into yaml 88 | recursive_hash_to_yml_string(tmphash) 89 | 90 | end 91 | 92 | -%> 93 | <%= @yml_string -%> 94 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 0.1.3 ( Sep 06, 2013 ) 2 | Exec path settings has been updated to fix warnings ( PR #37, #47 ) 3 | Adding define to install python bindings ( PR #43 ) 4 | Scope deprecation fixes ( PR #41 ) 5 | feature to install plugins ( PR #40 ) 6 | 7 | 0.1.2 ( Jun 21, 2013 ) 8 | Update rake file to ignore the param inherit 9 | Added missing documentation to the template define 10 | Fix for template define to allow multiple templates ( PR #36 by Bruce Morrison ) 11 | 12 | 0.1.1 ( Jun 14, 2013 ) 13 | Add Oracle Linux to the OS list ( PR #25 by Stas Alekseev ) 14 | Respect the restart_on_change on the defaults ( PR #29 by Simon Effenberg ) 15 | Make sure the config can be empty as advertised in the readme 16 | Remove dependency cycle when the defaults file is updated ( PR #31 by Bruce Morrison ) 17 | Enable retry on the template insert in case ES isn't started yet ( PR #32 by Bruce Morrison ) 18 | Update templates to avoid deprecation notice with Puppet 3.2.x 19 | Update template define to avoid auto insert issue with ES 20 | Update spec tests to reflect changes to template define 21 | 22 | 0.1.0 ( May 09, 2013 ) 23 | Populate .gitignore ( PR #19 by Igor Galić ) 24 | Add ability to install initfile ( PR #20 by Justin Lambert ) 25 | Add ability to manage default file* service parameters ( PR #21 by Mathieu Bornoz ) 26 | Providing complete containment of the module ( PR #24 by Brian Lalor ) 27 | Add ability to specify package version ( PR #25 by Justin Lambert ) 28 | Adding license file 29 | 30 | 0.0.7 ( Mar 23, 2013 ) 31 | Ensure config directory is created and managed ( PR #13 by Martin Seener ) 32 | Dont backup package if it changes 33 | Create explicit dependency on template directory ( PR #16 by Igor Galić ) 34 | Make the config directory variable ( PR #17 by Igor Galić and PR #18 by Vincent Janelle ) 35 | Fixing template define 36 | 37 | 0.0.6 ( Mar 05, 2013 ) 38 | Fixing issue with configuration not printing out arrays 39 | New feature to write the config hash shorter 40 | Updated readme to reflect the new feature 41 | Adding spec tests for config file generation 42 | 43 | 0.0.5 ( Mar 03, 2013 ) 44 | Option to disable restart on config file change ( PR #10 by Chris Boulton ) 45 | 46 | 0.0.4 ( Mar 02, 2013 ) 47 | Fixed a major issue with the config template ( Issue #9 ) 48 | 49 | 0.0.3 ( Mar 02, 2013 ) 50 | Adding spec tests 51 | Fixed init issue on Ubuntu ( Issue #6 by Marcus Furlong ) 52 | Fixed config template problem ( Issue #8 by surfchris ) 53 | New feature to manage templates 54 | 55 | 0.0.2 ( Feb 16, 2013 ) 56 | Feature to supply a package instead of being dependent on the repository 57 | Feature to install java in case one doesn't manage it externally 58 | Adding RedHat and Amazon as Operating systems 59 | fixed a typo - its a shard not a shared :) ( PR #5 by Martin Seener ) 60 | 61 | 0.0.1 ( Jan 13, 2013 ) 62 | Initial release of the module 63 | -------------------------------------------------------------------------------- /manifests/plugin.pp: -------------------------------------------------------------------------------- 1 | # == Define: elasticsearch::plugin 2 | # 3 | # This define allows you to install arbitrary Elasticsearch plugins 4 | # either by using the default repositories or by specifying an URL 5 | # 6 | # All default values are defined in the elasticsearch::params class. 7 | # 8 | # 9 | # === Parameters 10 | # 11 | # [*module_dir*] 12 | # Directory name where the module will be installed 13 | # Value type is string 14 | # Default value: None 15 | # This variable is required 16 | # 17 | # [*ensure*] 18 | # Whether the plugin will be installed or removed. 19 | # Set to 'absent' to ensure a plugin is not installed 20 | # Value type is string 21 | # Default value: present 22 | # This variable is optional 23 | # 24 | # [*url*] 25 | # Specify an URL where to download the plugin from. 26 | # Value type is string 27 | # Default value: None 28 | # This variable is optional 29 | # 30 | # 31 | # === Examples 32 | # 33 | # # From official repository 34 | # elasticsearch::plugin{'mobz/elasticsearch-head': module_dir => 'head'} 35 | # 36 | # # From custom url 37 | # elasticsearch::plugin{ 'elasticsearch-jetty': 38 | # module_dir => 'elasticsearch-jetty', 39 | # url => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.90.0.zip', 40 | # } 41 | # 42 | # === Authors 43 | # 44 | # * Matteo Sessa 45 | # * Dennis Konert 46 | # 47 | define elasticsearch::plugin( 48 | $module_dir, 49 | $ensure = 'present', 50 | $url = '' 51 | ) { 52 | 53 | require elasticsearch::params 54 | 55 | Exec { 56 | path => [ '/bin', '/usr/bin', '/usr/local/bin' ], 57 | cwd => '/', 58 | } 59 | 60 | $notify_elasticsearch = $elasticsearch::restart_on_change ? { 61 | false => undef, 62 | default => Class['elasticsearch::service'], 63 | } 64 | 65 | if ($module_dir != '') { 66 | validate_string($module_dir) 67 | } else { 68 | fail("module_dir undefined for plugin ${name}") 69 | } 70 | 71 | if ($url != '') { 72 | validate_string($url) 73 | $install_cmd = "${elasticsearch::plugintool} -install ${name} -url ${url}" 74 | $exec_rets = [0,1] 75 | } else { 76 | $install_cmd = "${elasticsearch::plugintool} -install ${name}" 77 | $exec_rets = [0,] 78 | } 79 | 80 | case $ensure { 81 | 'installed', 'present': { 82 | exec {"install-plugin-${name}": 83 | command => $install_cmd, 84 | creates => "${elasticsearch::plugindir}/${module_dir}", 85 | returns => $exec_rets, 86 | notify => $notify_elasticsearch, 87 | } 88 | } 89 | default: { 90 | exec {"remove-plugin-${name}": 91 | command => "${elasticsearch::plugintool} --remove ${module_dir}", 92 | onlyif => "test -d ${elasticsearch::plugindir}/${module_dir}", 93 | notify => $notify_elasticsearch, 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /manifests/params.pp: -------------------------------------------------------------------------------- 1 | # == Class: elasticsearch::params 2 | # 3 | # This class exists to 4 | # 1. Declutter the default value assignment for class parameters. 5 | # 2. Manage internally used module variables in a central place. 6 | # 7 | # Therefore, many operating system dependent differences (names, paths, ...) 8 | # are addressed in here. 9 | # 10 | # 11 | # === Parameters 12 | # 13 | # This class does not provide any parameters. 14 | # 15 | # 16 | # === Examples 17 | # 18 | # This class is not intended to be used directly. 19 | # 20 | # 21 | # === Links 22 | # 23 | # * {Puppet Docs: Using Parameterized Classes}[http://j.mp/nVpyWY] 24 | # 25 | # 26 | # === Authors 27 | # 28 | # * Richard Pijnenburg 29 | # 30 | class elasticsearch::params { 31 | 32 | #### Default values for the parameters of the main module class, init.pp 33 | 34 | # ensure 35 | $ensure = 'present' 36 | 37 | # autoupgrade 38 | $autoupgrade = false 39 | 40 | # restart on configuration change? 41 | $restart_on_change = true 42 | 43 | # service status 44 | $status = 'enabled' 45 | 46 | # configuration directory 47 | $confdir = '/etc/elasticsearch' 48 | 49 | # plugins directory 50 | $plugindir = '/usr/share/elasticsearch/plugins' 51 | 52 | # plugins helper binary 53 | $plugintool = '/usr/share/elasticsearch/bin/plugin' 54 | 55 | # default service settings 56 | $service_settings = { 57 | 'ES_USER' => 'elasticsearch', 58 | 'ES_GROUP' => 'elasticsearch', 59 | } 60 | 61 | #### Internal module values 62 | 63 | # packages 64 | case $::operatingsystem { 65 | 'CentOS', 'Fedora', 'Scientific', 'RedHat', 'Amazon', 'OracleLinux': { 66 | # main application 67 | $package = [ 'elasticsearch' ] 68 | } 69 | 'Debian', 'Ubuntu': { 70 | # main application 71 | $package = [ 'elasticsearch' ] 72 | } 73 | default: { 74 | fail("\"${module_name}\" provides no package default value 75 | for \"${::operatingsystem}\"") 76 | } 77 | } 78 | 79 | # service parameters 80 | case $::operatingsystem { 81 | 'CentOS', 'Fedora', 'Scientific', 'RedHat', 'Amazon', 'OracleLinux': { 82 | $service_name = 'elasticsearch' 83 | $service_hasrestart = true 84 | $service_hasstatus = true 85 | $service_pattern = $service_name 86 | $service_provider = 'redhat' 87 | $service_settings_path = "/etc/sysconfig/${service_name}" 88 | } 89 | 'Debian', 'Ubuntu': { 90 | $service_name = 'elasticsearch' 91 | $service_hasrestart = true 92 | $service_hasstatus = true 93 | $service_pattern = $service_name 94 | $service_provider = 'debian' 95 | $service_settings_path = "/etc/default/${service_name}" 96 | } 97 | default: { 98 | fail("\"${module_name}\" provides no service parameters 99 | for \"${::operatingsystem}\"") 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /spec/defines/template_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'elasticsearch::template', :type => 'define' do 4 | 5 | let(:title) { 'foo' } 6 | let(:facts) { {:operatingsystem => 'CentOS' }} 7 | let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}'} 8 | 9 | context "Add a template" do 10 | 11 | let :params do { 12 | :file => 'puppet:///path/to/foo.json', 13 | } end 14 | 15 | it { should contain_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') } 16 | it { should contain_exec('insert_template foo').with(:command => 'curl -s -XPUT http://localhost:9200/_template/foo -d @/etc/elasticsearch/templates_import/elasticsearch-template-foo.json', :unless => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1') } 17 | end 18 | 19 | context "Delete a template" do 20 | 21 | let :params do { 22 | :delete => true 23 | } end 24 | 25 | it { should_not contain_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') } 26 | it { should_not contain_exec('insert_template foo') } 27 | it { should contain_exec('delete_template foo').with(:command => 'curl -s -XDELETE http://localhost:9200/_template/foo', :notify => nil, :onlyif => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1' ) } 28 | end 29 | 30 | context "Replace a template" do 31 | 32 | let :params do { 33 | :replace => true, 34 | :file => 'puppet:///path/to/foo.json' 35 | } end 36 | 37 | it { should contain_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') } 38 | it { should contain_exec('insert_template foo').with(:command => 'curl -s -XPUT http://localhost:9200/_template/foo -d @/etc/elasticsearch/templates_import/elasticsearch-template-foo.json', :unless => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1') } 39 | it { should contain_exec('delete_template foo').with(:command => 'curl -s -XDELETE http://localhost:9200/_template/foo', :notify => 'Exec[insert_template foo]', :onlyif => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1' ) } 40 | 41 | end 42 | 43 | context "Try replace and delete at the same time" do 44 | 45 | let :params do { 46 | :replace => true, 47 | :delete => true, 48 | :file => 'puppet:///path/to/foo.json' 49 | } end 50 | 51 | it { expect { should raise_error(Puppet::Error) } } 52 | 53 | end 54 | 55 | context "Add template with alternative host" do 56 | 57 | let :params do { 58 | :file => 'puppet:///path/to/foo.json', 59 | :host => 'otherhost' 60 | } end 61 | 62 | it { should contain_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') } 63 | it { should contain_exec('insert_template foo').with(:command => 'curl -s -XPUT http://otherhost:9200/_template/foo -d @/etc/elasticsearch/templates_import/elasticsearch-template-foo.json', :unless => 'test $(curl -s \'http://otherhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1') } 64 | end 65 | 66 | end 67 | -------------------------------------------------------------------------------- /manifests/template.pp: -------------------------------------------------------------------------------- 1 | # == Define: elasticsearch::template 2 | # 3 | # This define allows you to insert, update or delete templates that are used within Elasticsearch for the indexes 4 | # 5 | # === Parameters 6 | # 7 | # [*file*] 8 | # File path of the template ( json file ) 9 | # Value type is string 10 | # Default value: undef 11 | # This variable is optional 12 | # 13 | # [*replace*] 14 | # Set to 'true' if you intend to replace the existing template 15 | # Value type is boolean 16 | # Default value: false 17 | # This variable is optional 18 | # 19 | # [*delete*] 20 | # Set to 'true' if you intend to delete the existing template 21 | # Value type is boolean 22 | # Default value: false 23 | # This variable is optional 24 | # 25 | # [*host*] 26 | # Host name or IP address of the ES instance to connect to 27 | # Value type is string 28 | # Default value: localhost 29 | # This variable is optional 30 | # 31 | # [*port*] 32 | # Port number of the ES instance to connect to 33 | # Value type is number 34 | # Default value: 9200 35 | # This variable is optional 36 | # 37 | # === Authors 38 | # 39 | # * Richard Pijnenburg 40 | # 41 | define elasticsearch::template( 42 | $file = undef, 43 | $replace = false, 44 | $delete = false, 45 | $host = 'localhost', 46 | $port = 9200 47 | ) { 48 | 49 | require elasticsearch 50 | 51 | Exec { 52 | path => [ '/bin', '/usr/bin', '/usr/local/bin' ], 53 | cwd => '/', 54 | } 55 | 56 | # Build up the url 57 | $es_url = "http://${host}:${port}/_template/${name}" 58 | 59 | # Can't do a replace and delete at the same time 60 | if $replace == true and $delete == true { 61 | fail('Replace and Delete cant be used together') 62 | } 63 | 64 | if $delete == false { 65 | # Fail when no file is supplied 66 | if $file == undef { 67 | fail('The variable "file" cannot be empty when inserting or updating a template') 68 | } 69 | } 70 | 71 | $file_ensure = $delete ? { 72 | true => 'absent', 73 | default => 'present' 74 | } 75 | 76 | $file_notify = $delete ? { 77 | true => undef, 78 | default => Exec[ "insert_template ${name}" ] 79 | } 80 | 81 | # place the template file 82 | file { "${elasticsearch::confdir}/templates_import/elasticsearch-template-${name}.json": 83 | ensure => $file_ensure, 84 | source => $file, 85 | notify => $file_notify, 86 | require => Exec[ 'mkdir_templates' ], 87 | } 88 | 89 | if $replace == true or $delete == true { 90 | 91 | # Only notify the insert_template call when we do a replace. 92 | $exec_notify = $replace ? { 93 | true => Exec[ "insert_template ${name}" ], 94 | default => undef 95 | } 96 | 97 | # Delete the existing template 98 | # First check if it exists of course 99 | exec { "delete_template ${name}": 100 | command => "curl -s -XDELETE ${es_url}", 101 | onlyif => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1", 102 | notify => $exec_notify 103 | } 104 | 105 | } 106 | 107 | # Insert the template if we don't delete an existing one 108 | # Before inserting we check if a template exists with that same name 109 | if $delete == false { 110 | exec { "insert_template ${name}": 111 | command => "curl -s -XPUT ${es_url} -d @${elasticsearch::confdir}/templates_import/elasticsearch-template-${name}.json", 112 | unless => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1", 113 | refreshonly => true, 114 | tries => 3, 115 | try_sleep => 10 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /manifests/service.pp: -------------------------------------------------------------------------------- 1 | # == Class: elasticsearch::service 2 | # 3 | # This class exists to coordinate all service management related actions, 4 | # functionality and logical units in a central place. 5 | # 6 | # Note: "service" is the Puppet term and type for background processes 7 | # in general and is used in a platform-independent way. E.g. "service" means 8 | # "daemon" in relation to Unix-like systems. 9 | # 10 | # 11 | # === Parameters 12 | # 13 | # This class does not provide any parameters. 14 | # 15 | # 16 | # === Examples 17 | # 18 | # This class may be imported by other classes to use its functionality: 19 | # class { 'elasticsearch::service': } 20 | # 21 | # It is not intended to be used directly by external resources like node 22 | # definitions or other modules. 23 | # 24 | # 25 | # === Authors 26 | # 27 | # * Richard Pijnenburg 28 | # 29 | class elasticsearch::service { 30 | 31 | include elasticsearch 32 | 33 | $notify_elasticsearch = $elasticsearch::restart_on_change ? { 34 | false => undef, 35 | default => Service['elasticsearch'], 36 | } 37 | 38 | #### Service management 39 | 40 | # set params: in operation 41 | if $elasticsearch::ensure == 'present' { 42 | 43 | case $elasticsearch::status { 44 | # make sure service is currently running, start it on boot 45 | 'enabled': { 46 | $service_ensure = 'running' 47 | $service_enable = true 48 | } 49 | # make sure service is currently stopped, do not start it on boot 50 | 'disabled': { 51 | $service_ensure = 'stopped' 52 | $service_enable = false 53 | } 54 | # make sure service is currently running, do not start it on boot 55 | 'running': { 56 | $service_ensure = 'running' 57 | $service_enable = false 58 | } 59 | # do not start service on boot, do not care whether currently running or not 60 | 'unmanaged': { 61 | $service_ensure = undef 62 | $service_enable = false 63 | } 64 | # unknown status 65 | # note: don't forget to update the parameter check in init.pp if you 66 | # add a new or change an existing status. 67 | default: { 68 | fail("\"${elasticsearch::status}\" is an unknown service status value") 69 | } 70 | } 71 | 72 | # set params: removal 73 | } else { 74 | 75 | # make sure the service is stopped and disabled (the removal itself will be 76 | # done by package.pp) 77 | $service_ensure = 'stopped' 78 | $service_enable = false 79 | 80 | } 81 | 82 | file {$elasticsearch::params::service_settings_path: 83 | ensure => file, 84 | content => template("${module_name}/etc/default/elasticsearch.erb"), 85 | owner => 'root', 86 | group => 'root', 87 | mode => '0644', 88 | notify => $notify_elasticsearch, 89 | } 90 | 91 | if $elasticsearch::status != 'unmanaged' and $elasticsearch::initfile != undef { 92 | # Write service file 93 | file { '/etc/init.d/elasticsearch': 94 | ensure => present, 95 | source => $elasticsearch::initfile, 96 | owner => 'root', 97 | group => 'root', 98 | mode => '0555', 99 | before => Service[ 'elasticsearch' ] 100 | } 101 | } 102 | 103 | # action 104 | service { 'elasticsearch': 105 | ensure => $service_ensure, 106 | enable => $service_enable, 107 | name => $elasticsearch::params::service_name, 108 | hasstatus => $elasticsearch::params::service_hasstatus, 109 | hasrestart => $elasticsearch::params::service_hasrestart, 110 | pattern => $elasticsearch::params::service_pattern, 111 | provider => $elasticsearch::params::service_provider, 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # puppet-elasticsearch 2 | 3 | A puppet module for managing elasticsearch nodes 4 | 5 | http://www.elasticsearch.org/ 6 | 7 | [![Build Status](https://travis-ci.org/elasticsearch/puppet-elasticsearch.png?branch=master)](https://travis-ci.org/elasticsearch/puppet-elasticsearch) 8 | 9 | ## Usage 10 | 11 | Installation, make sure service is running and will be started at boot time: 12 | 13 | class { 'elasticsearch': } 14 | 15 | Install a certain version: 16 | 17 | class { 'elasticsearch': 18 | version => '0.90.3' 19 | } 20 | 21 | Removal/decommissioning: 22 | 23 | class { 'elasticsearch': 24 | ensure => 'absent', 25 | } 26 | 27 | Install everything but disable service(s) afterwards: 28 | 29 | class { 'elasticsearch': 30 | status => 'disabled', 31 | } 32 | 33 | Disable automated restart of Elasticsearch on config file change: 34 | 35 | class { 'elasticsearch': 36 | restart_on_change => false 37 | } 38 | 39 | For the config variable a hash needs to be passed: 40 | 41 | class { 'elasticsearch': 42 | config => { 43 | 'node' => { 44 | 'name' => 'elasticsearch001' 45 | }, 46 | 'index' => { 47 | 'number_of_replicas' => '0', 48 | 'number_of_shards' => '5' 49 | }, 50 | 'network' => { 51 | 'host' => $::ipaddress 52 | } 53 | } 54 | } 55 | 56 | Short write up of the config hash is also possible. 57 | 58 | Instead of writing the full hash representation: 59 | 60 | class { 'elasticsearch': 61 | config => { 62 | 'cluster' => { 63 | 'name' => 'ClusterName', 64 | 'routing' => { 65 | 'allocation' => { 66 | 'awareness' => { 67 | 'attributes' => 'rack' 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | You can write the dotted key naming: 76 | 77 | class { 'elasticsearch': 78 | config => { 79 | 'cluster' => { 80 | 'name' => 'ClusterName', 81 | 'routing.allocation.awareness.attributes' => 'rack' 82 | } 83 | } 84 | } 85 | 86 | ## Defaults file 87 | 88 | You can populate the defaults file ( /etc/defaults/elasticsearch or /etc/sysconfig/elasticsearch ) 89 | 90 | class { 'elasticsearch': 91 | service_settings => { 'ES_USER' => 'elasticsearch', 'ES_GROUP' => 'elasticsearch' } 92 | } 93 | 94 | ## Manage templates 95 | 96 | ### Add a new template 97 | 98 | elasticsearch::template { 'templatename': 99 | file => 'puppet:///path/to/template.json' 100 | } 101 | 102 | ### Delete a template 103 | 104 | elasticsearch::template { 'templatename': 105 | delete => true 106 | } 107 | 108 | ### Replace a template 109 | 110 | elasticsearch::template { 'templatename': 111 | file => 'puppet:///path/to/template.json', 112 | replace => true 113 | } 114 | 115 | ### Host 116 | 117 | Default it uses localhost:9200 as host. you can change this with the 'host' and 'port' variables 118 | 119 | elasticsearch::template { 'templatename': 120 | host => $::ipaddress, 121 | port => 9200 122 | } 123 | 124 | ## Bindings / clients 125 | 126 | Install [a variety of python bindings](http://www.elasticsearch.org/guide/clients/): 127 | 128 | elasticsearch::python { "rawes": } 129 | 130 | 131 | ## Plugins 132 | 133 | Install [a variety of plugins](http://www.elasticsearch.org/guide/clients/): 134 | 135 | ### From official repository: 136 | 137 | elasticsearch::plugin{'mobz/elasticsearch-head': 138 | module_dir => 'head' 139 | } 140 | 141 | ### From custom url: 142 | 143 | elasticsearch::plugin{ 'elasticsearch-jetty': 144 | module_dir => 'elasticsearch-jetty', 145 | url => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.90.0.zip' 146 | } 147 | 148 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # == Class: elasticsearch 2 | # 3 | # This class is able to install or remove elasticsearch on a node. 4 | # It manages the status of the related service. 5 | # 6 | # === Parameters 7 | # 8 | # [*config*] 9 | # Hash. Hash that defines the configuration. 10 | # 11 | # [*ensure*] 12 | # String. Controls if the managed resources shall be present or 13 | # absent. If set to absent: 14 | # * The managed software packages are being uninstalled. 15 | # * Any traces of the packages will be purged as good as possible. This may 16 | # include existing configuration files. The exact behavior is provider 17 | # dependent. Q.v.: 18 | # * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] 19 | # * {Puppet's package provider source code}[http://j.mp/wtVCaL] 20 | # * System modifications (if any) will be reverted as good as possible 21 | # (e.g. removal of created users, services, changed log settings, ...). 22 | # * This is thus destructive and should be used with care. 23 | # Defaults to present. 24 | # 25 | # [*autoupgrade*] 26 | # Boolean. If set to true, any managed package gets upgraded 27 | # on each Puppet run when the package provider is able to find a newer 28 | # version than the present one. The exact behavior is provider dependent. 29 | # Q.v.: 30 | # * Puppet type reference: {package, "upgradeable"}[http://j.mp/xbxmNP] 31 | # * {Puppet's package provider source code}[http://j.mp/wtVCaL] 32 | # Defaults to false. 33 | # 34 | # [*status*] 35 | # String to define the status of the service. Possible values: 36 | # * enabled: Service is running and will be started at boot time. 37 | # * disabled: Service is stopped and will not be started at boot 38 | # time. 39 | # * running: Service is running but will not be started at boot time. 40 | # You can use this to start a service on the first Puppet run instead of 41 | # the system startup. 42 | # * unmanaged: Service will not be started at boot time and Puppet 43 | # does not care whether the service is running or not. For example, this may 44 | # be useful if a cluster management software is used to decide when to start 45 | # the service plus assuring it is running on the desired node. 46 | # Defaults to enabled. The singular form ("service") is used for the 47 | # sake of convenience. Of course, the defined status affects all services if 48 | # more than one is managed (see service.pp to check if this is the 49 | # case). 50 | # 51 | # [*restart_on_change*] 52 | # Boolean that determines if ElasticSearch should be automatically restarted 53 | # whenever the configuration changes. Disabling automatic restarts on config 54 | # changes may be desired in an environment where you need to ensure restarts 55 | # occur in a controlled/rolling manner rather than during a Puppet run. 56 | # 57 | # Defaults to true, which will restart ElasticSearch on any config 58 | # change. Setting to false disables the automatic restart. 59 | # 60 | # [*confdir*] 61 | # Path to directory containing the elasticsearch configuration. 62 | # Use this setting if your packages deviate from the norm (/etc/elasticsearch) 63 | # 64 | # [*plugindir*] 65 | # Path to directory containing the elasticsearch plugins 66 | # Use this setting if your packages deviate from the norm (/usr/share/elasticsearch/plugins) 67 | # 68 | # [*plugintool*] 69 | # Path to directory containing the elasticsearch plugin installation script 70 | # Use this setting if your packages deviate from the norm (/usr/share/elasticsearch/bin/plugin) 71 | # 72 | # [*service_settings*] 73 | # A hash to define the default service settings. Values must be consistent 74 | # with those defined in the init script and overwritten from the default 75 | # file (/etc/default/elasticsearch or /etc/sysconfig/elasticsearch). 76 | # 77 | # [*initfile*] 78 | # Source file to be used as the elasticsearch init script. 79 | # 80 | # [*version*] 81 | # String to set the specific version you want to install. 82 | # Defaults to false. 83 | # 84 | # 85 | # The default values for the parameters are set in elasticsearch::params. Have 86 | # a look at the corresponding params.pp manifest file if you need more 87 | # technical information about them. 88 | # 89 | # 90 | # === Examples 91 | # 92 | # * Installation, make sure service is running and will be started at boot time: 93 | # class { 'elasticsearch': } 94 | # 95 | # * Removal/decommissioning: 96 | # class { 'elasticsearch': 97 | # ensure => 'absent', 98 | # } 99 | # 100 | # * Install everything but disable service(s) afterwards 101 | # class { 'elasticsearch': 102 | # status => 'disabled', 103 | # } 104 | # 105 | # * For the config variable a hash needs to be passed: 106 | # 107 | # class { 'elasticsearch': 108 | # config => { 109 | # 'node' => { 110 | # 'name' => 'elasticsearch001' 111 | # }, 112 | # 'index' => { 113 | # 'number_of_replicas' => '0', 114 | # 'number_of_shards' => '5' 115 | # }, 116 | # 'network' => { 117 | # 'host' => $::ipaddress 118 | # } 119 | # } 120 | # } 121 | # 122 | # === Authors 123 | # 124 | # * Richard Pijnenburg 125 | # 126 | class elasticsearch( 127 | $config = {}, 128 | $ensure = $elasticsearch::params::ensure, 129 | $autoupgrade = $elasticsearch::params::autoupgrade, 130 | $status = $elasticsearch::params::status, 131 | $restart_on_change = $elasticsearch::params::restart_on_change, 132 | $confdir = $elasticsearch::params::confdir, 133 | $plugindir = $elasticsearch::params::plugindir, 134 | $plugintool = $elasticsearch::params::plugintool, 135 | $service_settings = $elasticsearch::params::service_settings, 136 | $pkg_source = undef, 137 | $version = false, 138 | $java_install = false, 139 | $java_package = undef, 140 | $initfile = undef 141 | ) inherits elasticsearch::params { 142 | 143 | #### Validate parameters 144 | 145 | # ensure 146 | if ! ($ensure in [ 'present', 'absent' ]) { 147 | fail("\"${ensure}\" is not a valid ensure parameter value") 148 | } 149 | 150 | # autoupgrade 151 | validate_bool($autoupgrade) 152 | 153 | # service status 154 | if ! ($status in [ 'enabled', 'disabled', 'running', 'unmanaged' ]) { 155 | fail("\"${status}\" is not a valid status parameter value") 156 | } 157 | 158 | # Config 159 | validate_hash($config) 160 | validate_bool($restart_on_change) 161 | 162 | #### Manage actions 163 | anchor {'elasticsearch::begin': } 164 | anchor {'elasticsearch::end': } 165 | 166 | # package(s) 167 | class { 'elasticsearch::package': } 168 | 169 | # config 170 | class { 'elasticsearch::config': } 171 | 172 | # service(s) 173 | class { 'elasticsearch::service': } 174 | 175 | if $java_install == true { 176 | # Install java 177 | class { 'elasticsearch::java': } 178 | 179 | # ensure we first java java and then manage the service 180 | Anchor['elasticsearch::begin'] 181 | -> Class['elasticsearch::java'] 182 | -> Class['elasticsearch::service'] 183 | } 184 | 185 | #### Manage relationships 186 | 187 | if $ensure == 'present' { 188 | # we need the software before configuring it 189 | Anchor['elasticsearch::begin'] 190 | -> Class['elasticsearch::package'] 191 | -> Class['elasticsearch::config'] 192 | 193 | # we need the software before running a service 194 | Class['elasticsearch::package'] -> Class['elasticsearch::service'] 195 | Class['elasticsearch::config'] -> Class['elasticsearch::service'] 196 | 197 | Class['elasticsearch::service'] 198 | -> Anchor['elasticsearch::end'] 199 | } else { 200 | 201 | # make sure all services are getting stopped before software removal 202 | Anchor['elasticsearch::begin'] 203 | -> Class['elasticsearch::service'] 204 | -> Class['elasticsearch::package'] 205 | -> Anchor['elasticsearch::end'] 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /spec/classes/elasticsearch_init_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'elasticsearch', :type => 'class' do 4 | 5 | let :params do { 6 | :config => { 'node' => { 'name' => 'test' } } 7 | } end 8 | 9 | context "On Debian OS" do 10 | 11 | let :facts do { 12 | :operatingsystem => 'Debian' 13 | } end 14 | 15 | # init.pp 16 | it { should contain_class('elasticsearch::package') } 17 | it { should contain_class('elasticsearch::config') } 18 | it { should contain_class('elasticsearch::service') } 19 | 20 | # package.pp 21 | it { should contain_package('elasticsearch') } 22 | 23 | # service.pp 24 | it { should contain_service('elasticsearch') } 25 | 26 | # config.pp 27 | 28 | end 29 | 30 | context "On Ubuntu OS" do 31 | 32 | let :facts do { 33 | :operatingsystem => 'Ubuntu' 34 | } end 35 | 36 | # init.pp 37 | it { should contain_class('elasticsearch::package') } 38 | it { should contain_class('elasticsearch::config') } 39 | it { should contain_class('elasticsearch::service') } 40 | 41 | # package.pp 42 | it { should contain_package('elasticsearch') } 43 | 44 | # service.pp 45 | it { should contain_service('elasticsearch') } 46 | 47 | # config.pp 48 | 49 | end 50 | 51 | context "On CentOS OS" do 52 | 53 | let :facts do { 54 | :operatingsystem => 'CentOS' 55 | } end 56 | 57 | # init.pp 58 | it { should contain_class('elasticsearch::package') } 59 | it { should contain_class('elasticsearch::config') } 60 | it { should contain_class('elasticsearch::service') } 61 | 62 | # package.pp 63 | it { should contain_package('elasticsearch') } 64 | 65 | # service.pp 66 | it { should contain_service('elasticsearch') } 67 | 68 | # config.pp 69 | 70 | end 71 | 72 | context "On RedHat OS" do 73 | 74 | let :facts do { 75 | :operatingsystem => 'Redhat' 76 | } end 77 | 78 | # init.pp 79 | it { should contain_class('elasticsearch::package') } 80 | it { should contain_class('elasticsearch::config') } 81 | it { should contain_class('elasticsearch::service') } 82 | 83 | # package.pp 84 | it { should contain_package('elasticsearch') } 85 | 86 | # service.pp 87 | it { should contain_service('elasticsearch') } 88 | 89 | # config.pp 90 | 91 | end 92 | 93 | context "On Fedora OS" do 94 | 95 | let :facts do { 96 | :operatingsystem => 'Fedora' 97 | } end 98 | 99 | # init.pp 100 | it { should contain_class('elasticsearch::package') } 101 | it { should contain_class('elasticsearch::config') } 102 | it { should contain_class('elasticsearch::service') } 103 | 104 | # package.pp 105 | it { should contain_package('elasticsearch') } 106 | 107 | # service.pp 108 | it { should contain_service('elasticsearch') } 109 | 110 | # config.pp 111 | 112 | end 113 | 114 | context "On Scientific OS" do 115 | 116 | let :facts do { 117 | :operatingsystem => 'Scientific' 118 | } end 119 | 120 | # init.pp 121 | it { should contain_class('elasticsearch::package') } 122 | it { should contain_class('elasticsearch::config') } 123 | it { should contain_class('elasticsearch::service') } 124 | 125 | # package.pp 126 | it { should contain_package('elasticsearch') } 127 | 128 | # service.pp 129 | it { should contain_service('elasticsearch') } 130 | 131 | # config.pp 132 | 133 | end 134 | 135 | context "On Amazon OS" do 136 | 137 | let :facts do { 138 | :operatingsystem => 'Amazon' 139 | } end 140 | 141 | # init.pp 142 | it { should contain_class('elasticsearch::package') } 143 | it { should contain_class('elasticsearch::config') } 144 | it { should contain_class('elasticsearch::service') } 145 | 146 | # package.pp 147 | it { should contain_package('elasticsearch') } 148 | 149 | # service.pp 150 | it { should contain_service('elasticsearch') } 151 | 152 | # config.pp 153 | 154 | end 155 | 156 | context "On OracleLinux OS" do 157 | 158 | let :facts do { 159 | :operatingsystem => 'OracleLinux' 160 | } end 161 | 162 | # init.pp 163 | it { should contain_class('elasticsearch::package') } 164 | it { should contain_class('elasticsearch::config') } 165 | it { should contain_class('elasticsearch::service') } 166 | 167 | # package.pp 168 | it { should contain_package('elasticsearch') } 169 | 170 | # service.pp 171 | it { should contain_service('elasticsearch') } 172 | 173 | # config.pp 174 | 175 | end 176 | 177 | context "On an unknown OS" do 178 | 179 | let :facts do { 180 | :operatingsystem => 'Darwin' 181 | } end 182 | 183 | it { expect { should raise_error(Puppet::Error) } } 184 | 185 | end 186 | 187 | context "install using an alternative package source" do 188 | 189 | context "with a debian package" do 190 | 191 | let :facts do { 192 | :operatingsystem => 'Debian' 193 | } end 194 | 195 | let :params do { 196 | :pkg_source => 'puppet:///path/to/package.deb', 197 | :config => { 'node' => { 'name' => 'test' } } 198 | } end 199 | 200 | it { should contain_file('/tmp/package.deb').with(:source => 'puppet:///path/to/package.deb') } 201 | 202 | it { should contain_package('elasticsearch').with(:source => '/tmp/package.deb', :provider => 'dpkg') } 203 | 204 | end 205 | 206 | context "with a redhat package" do 207 | 208 | let :facts do { 209 | :operatingsystem => 'CentOS' 210 | } end 211 | 212 | let :params do { 213 | :pkg_source => 'puppet:///path/to/package.rpm', 214 | :config => { 'node' => { 'name' => 'test' } } 215 | } end 216 | 217 | it { should contain_file('/tmp/package.rpm').with(:source => 'puppet:///path/to/package.rpm') } 218 | 219 | it { should contain_package('elasticsearch').with(:source => '/tmp/package.rpm', :provider => 'rpm') } 220 | 221 | end 222 | 223 | context "with an unsupported package" do 224 | 225 | let :facts do { 226 | :operatingsystem => 'CentOS' 227 | } end 228 | 229 | let :params do { 230 | :pkg_source => 'puppet:///path/to/package.yaml', 231 | :config => { 'node' => { 'name' => 'test' } } 232 | } end 233 | 234 | it { expect { should raise_error(Puppet::Error) } } 235 | 236 | end 237 | 238 | end 239 | 240 | context "install java" do 241 | 242 | let :params do { 243 | :java_install => true, 244 | :config => { 'node' => { 'name' => 'test' } } 245 | } end 246 | 247 | context "On a Debian OS" do 248 | 249 | let :facts do { 250 | :operatingsystem => 'Debian' 251 | } end 252 | 253 | it { should contain_package('openjdk-6-jre-headless') } 254 | 255 | end 256 | 257 | context "On an Ubuntu OS" do 258 | 259 | let :facts do { 260 | :operatingsystem => 'Ubuntu' 261 | } end 262 | 263 | it { should contain_package('openjdk-6-jre-headless') } 264 | 265 | end 266 | 267 | context "On a CentOS OS " do 268 | 269 | let :facts do { 270 | :operatingsystem => 'CentOS' 271 | } end 272 | 273 | it { should contain_package('java-1.6.0-openjdk') } 274 | 275 | end 276 | 277 | context "On a RedHat OS " do 278 | 279 | let :facts do { 280 | :operatingsystem => 'Redhat' 281 | } end 282 | 283 | it { should contain_package('java-1.6.0-openjdk') } 284 | 285 | end 286 | 287 | context "On a Fedora OS " do 288 | 289 | let :facts do { 290 | :operatingsystem => 'Fedora' 291 | } end 292 | 293 | it { should contain_package('java-1.6.0-openjdk') } 294 | 295 | end 296 | 297 | context "On a Scientific OS " do 298 | 299 | let :facts do { 300 | :operatingsystem => 'Scientific' 301 | } end 302 | 303 | it { should contain_package('java-1.6.0-openjdk') } 304 | 305 | end 306 | 307 | context "On a Amazon OS " do 308 | 309 | let :facts do { 310 | :operatingsystem => 'Amazon' 311 | } end 312 | 313 | it { should contain_package('java-1.6.0-openjdk') } 314 | 315 | end 316 | 317 | context "On a OracleLinux OS " do 318 | 319 | let :facts do { 320 | :operatingsystem => 'OracleLinux' 321 | } end 322 | 323 | it { should contain_package('java-1.6.0-openjdk') } 324 | 325 | end 326 | 327 | context "On an unknown OS" do 328 | 329 | let :facts do { 330 | :operatingsystem => 'Darwin' 331 | } end 332 | 333 | it { expect { should raise_error(Puppet::Error) } } 334 | 335 | end 336 | 337 | context "Custom java package" do 338 | 339 | let :facts do { 340 | :operatingsystem => 'CentOS' 341 | } end 342 | 343 | let :params do { 344 | :java_install => true, 345 | :java_package => 'java-1.7.0-openjdk', 346 | :config => { 'node' => { 'name' => 'test' } } 347 | } end 348 | 349 | it { should contain_package('java-1.7.0-openjdk') } 350 | 351 | end 352 | 353 | end 354 | 355 | context "test restarts on configuration change" do 356 | 357 | let :facts do { 358 | :operatingsystem => 'CentOS' 359 | } end 360 | 361 | context "does not restart when restart_on_change is false" do 362 | let :params do { 363 | :config => { 'node' => { 'name' => 'test' } }, 364 | :restart_on_change => false, 365 | } end 366 | 367 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').without_notify } 368 | end 369 | 370 | context "restarts when restart_on_change is true" do 371 | let :params do { 372 | :config => { 'node' => { 'name' => 'test' } }, 373 | :restart_on_change => true, 374 | } end 375 | 376 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:notify => "Class[Elasticsearch::Service]") } 377 | end 378 | 379 | end 380 | 381 | context "test content of default service file" do 382 | 383 | context "On a CentOS OS" do 384 | 385 | let :facts do { 386 | :operatingsystem => 'CentOS' 387 | } end 388 | 389 | context "set a value" do 390 | 391 | let :params do { 392 | :config => { 'node' => { 'name' => 'test' } }, 393 | :service_settings => { 'ES_USER' => 'elasticsearch', 'ES_GROUP' => 'elasticsearch' } 394 | } end 395 | 396 | it { should contain_file('/etc/sysconfig/elasticsearch').with(:content => "### MANAGED BY PUPPET ###\n\nES_GROUP=elasticsearch\nES_USER=elasticsearch\n") } 397 | 398 | end 399 | 400 | end 401 | 402 | context "On a Debian OS" do 403 | 404 | let :facts do { 405 | :operatingsystem => 'Debian' 406 | } end 407 | 408 | context "set a value" do 409 | 410 | let :params do { 411 | :config => { 'node' => { 'name' => 'test' } }, 412 | :service_settings => { 'ES_USER' => 'elasticsearch', 'ES_GROUP' => 'elasticsearch' } 413 | } end 414 | 415 | it { should contain_file('/etc/default/elasticsearch').with(:content => "### MANAGED BY PUPPET ###\n\nES_GROUP=elasticsearch\nES_USER=elasticsearch\n") } 416 | 417 | end 418 | 419 | end 420 | 421 | end 422 | 423 | context "test content of config file" do 424 | 425 | let :facts do { 426 | :operatingsystem => 'CentOS' 427 | } end 428 | 429 | context "with nothing set" do 430 | 431 | let :params do { 432 | } end 433 | 434 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n") } 435 | 436 | end 437 | 438 | context "set a value" do 439 | 440 | let :params do { 441 | :config => { 'node' => { 'name' => 'test' } } 442 | } end 443 | 444 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nnode: \n name: test\n") } 445 | 446 | end 447 | 448 | context "set a value to true" do 449 | 450 | let :params do { 451 | :config => { 'node' => { 'master' => true } } 452 | } end 453 | 454 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nnode: \n master: true\n") } 455 | 456 | end 457 | 458 | context "set a value to false" do 459 | 460 | let :params do { 461 | :config => { 'node' => { 'data' => false } } 462 | } end 463 | 464 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nnode: \n data: false\n") } 465 | end 466 | 467 | context "deeper hash and multiple keys" do 468 | 469 | let :params do { 470 | :config => { 'index' => { 'routing' => { 'allocation' => { 'include' => 'tag1', 'exclude' => [ 'tag2', 'tag3' ] } } }, 'node' => { 'name' => 'somename' } } 471 | } end 472 | 473 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nindex: \n routing: \n allocation: \n exclude: \n - tag2\n - tag3\n include: tag1\nnode: \n name: somename\n") } 474 | end 475 | 476 | context "Combination of full hash and shorted write up keys" do 477 | 478 | let :params do { 479 | :config => { 'node' => { 'name' => 'NodeName', 'rack' => 46 }, 'boostrap.mlockall' => true, 'cluster' => { 'name' => 'ClusterName', 'routing.allocation.awareness.attributes' => 'rack' }, 'discovery.zen' => { 'ping.unicast.hosts'=> [ "host1", "host2" ], 'minimum_master_nodes' => 3, 'ping.multicast.enabled' => false }, 'gateway' => { 'expected_nodes' => 4, 'recover_after_nodes' => 3 }, 'network.host' => '123.123.123.123' } 480 | } end 481 | 482 | it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nboostrap: \n mlockall: true\ncluster: \n name: ClusterName\n routing: \n allocation: \n awareness: \n attributes: rack\ndiscovery: \n zen: \n minimum_master_nodes: 3\n ping: \n multicast: \n enabled: false\n unicast: \n hosts: \n - host1\n - host2\ngateway: \n expected_nodes: 4\n recover_after_nodes: 3\nnetwork: \n host: 123.123.123.123\nnode: \n name: NodeName\n rack: 46\n") } 483 | 484 | end 485 | 486 | end 487 | 488 | context "try with different configdir" do 489 | 490 | let :facts do { 491 | :operatingsystem => 'CentOS' 492 | } end 493 | 494 | let :params do { 495 | :config => { 'node' => { 'name' => 'test' } }, 496 | :confdir => '/opt/elasticsearch/etc' 497 | } end 498 | 499 | it { should contain_file('/opt/elasticsearch/etc/elasticsearch.yml') } 500 | 501 | end 502 | 503 | context "install init script" do 504 | 505 | let :facts do { 506 | :operatingsystem => 'CentOS' 507 | } end 508 | 509 | context "default" do 510 | 511 | let :params do { 512 | :config => { 'node' => { 'name' => 'test' } } 513 | } end 514 | 515 | it { should_not contain_file('/etc/init.d/elasticsearch') } 516 | 517 | end 518 | 519 | context "when unmanaged" do 520 | 521 | let :params do { 522 | :config => { 'node' => { 'name' => 'test' } }, 523 | :status => 'unmanaged', 524 | :initfile => 'puppet:///data/elasticsearch/elasticsearch.init' 525 | } end 526 | 527 | it { should_not contain_file('/etc/init.d/elasticsearch') } 528 | 529 | end 530 | 531 | context "when not unmanaged" do 532 | 533 | let :params do { 534 | :config => { 'node' => { 'name' => 'test' } }, 535 | :initfile => 'puppet:///data/elasticsearch/elasticsearch.init' 536 | } end 537 | 538 | it { should contain_file('/etc/init.d/elasticsearch').with(:source => 'puppet:///data/elasticsearch/elasticsearch.init') } 539 | 540 | end 541 | 542 | end 543 | 544 | context "package options" do 545 | 546 | let :facts do { 547 | :operatingsystem => 'CentOS' 548 | } end 549 | 550 | context "default" do 551 | 552 | let :params do { 553 | :config => { 'node' => { 'name' => 'test' } } 554 | } end 555 | 556 | it { should contain_package('elasticsearch').with(:ensure => 'present') } 557 | 558 | end 559 | 560 | context "when autoupgrade is true" do 561 | 562 | let :params do { 563 | :config => { 'node' => { 'name' => 'test' } }, 564 | :autoupgrade => true 565 | } end 566 | 567 | it { should contain_package('elasticsearch').with(:ensure => 'latest') } 568 | 569 | end 570 | 571 | context "when version is set" do 572 | 573 | let :params do { 574 | :config => { 'node' => { 'name' => 'test' } }, 575 | :version => '0.20.5' 576 | } end 577 | 578 | it { should contain_package('elasticsearch').with(:ensure => '0.20.5') } 579 | 580 | end 581 | 582 | context "when absent" do 583 | 584 | let :params do { 585 | :config => { 'node' => { 'name' => 'test' } }, 586 | :ensure => 'absent' 587 | } end 588 | 589 | it { should contain_package('elasticsearch').with(:ensure => 'purged') } 590 | 591 | end 592 | 593 | end 594 | 595 | end 596 | 597 | --------------------------------------------------------------------------------