├── .editorconfig ├── .fixtures.yml ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── labeler.yml ├── release.yml └── workflows │ ├── ci.yml │ ├── labeler.yml │ ├── prepare_release.yml │ └── release.yml ├── .gitignore ├── .msync.yml ├── .overcommit.yml ├── .pmtignore ├── .puppet-lint.rc ├── .rubocop.yml ├── .rubocop_todo.yml ├── .sync.yml ├── CHANGELOG.md ├── CONTRIBUTORS ├── Gemfile ├── HISTORY.md ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── data ├── common.yaml ├── distro │ ├── Amazon.yaml │ ├── Amazon │ │ └── 2.yaml │ ├── Debian │ │ └── 7.yaml │ └── Ubuntu │ │ ├── 12.04.yaml │ │ └── 14.04.yaml ├── kernel │ ├── Darwin.yaml │ ├── Linux.yaml │ └── OpenBSD.yaml └── os │ ├── Debian.yaml │ ├── Gentoo.yaml │ ├── RedHat.yaml │ ├── RedHat │ ├── 5.yaml │ └── 6.yaml │ ├── Suse.yaml │ └── Suse │ └── 11.yaml ├── files └── etc │ └── init.d │ ├── elasticsearch.Debian.erb │ ├── elasticsearch.OpenBSD.erb │ ├── elasticsearch.RedHat.erb │ ├── elasticsearch.SLES.erb │ ├── elasticsearch.openrc.erb │ └── elasticsearch.systemd.erb ├── hiera.yaml ├── lib ├── facter │ └── es_facts.rb ├── puppet │ ├── feature │ │ └── elasticsearch_shield_users_native.rb │ ├── parser │ │ └── functions │ │ │ ├── array_suffix.rb │ │ │ ├── concat_merge.rb │ │ │ ├── deep_implode.rb │ │ │ ├── es_plugin_name.rb │ │ │ └── plugin_dir.rb │ ├── provider │ │ ├── elastic_parsedfile.rb │ │ ├── elastic_plugin.rb │ │ ├── elastic_rest.rb │ │ ├── elastic_user_command.rb │ │ ├── elastic_user_roles.rb │ │ ├── elastic_yaml.rb │ │ ├── elasticsearch_component_template │ │ │ └── ruby.rb │ │ ├── elasticsearch_ilm_policy │ │ │ └── ruby.rb │ │ ├── elasticsearch_index │ │ │ └── ruby.rb │ │ ├── elasticsearch_index_template │ │ │ └── ruby.rb │ │ ├── elasticsearch_keystore │ │ │ └── ruby.rb │ │ ├── elasticsearch_license │ │ │ └── xpack.rb │ │ ├── elasticsearch_pipeline │ │ │ └── ruby.rb │ │ ├── elasticsearch_plugin │ │ │ └── ruby.rb │ │ ├── elasticsearch_role │ │ │ └── ruby.rb │ │ ├── elasticsearch_role_mapping │ │ │ └── ruby.rb │ │ ├── elasticsearch_slm_policy │ │ │ └── ruby.rb │ │ ├── elasticsearch_snapshot_repository │ │ │ └── ruby.rb │ │ ├── elasticsearch_template │ │ │ └── ruby.rb │ │ ├── elasticsearch_user │ │ │ └── ruby.rb │ │ ├── elasticsearch_user_file │ │ │ └── ruby.rb │ │ ├── elasticsearch_user_roles │ │ │ └── ruby.rb │ │ └── es_instance_conn_validator │ │ │ └── tcp_port.rb │ ├── type │ │ ├── elasticsearch_component_template.rb │ │ ├── elasticsearch_ilm_policy.rb │ │ ├── elasticsearch_index.rb │ │ ├── elasticsearch_index_template.rb │ │ ├── elasticsearch_keystore.rb │ │ ├── elasticsearch_license.rb │ │ ├── elasticsearch_pipeline.rb │ │ ├── elasticsearch_plugin.rb │ │ ├── elasticsearch_role.rb │ │ ├── elasticsearch_role_mapping.rb │ │ ├── elasticsearch_slm_policy.rb │ │ ├── elasticsearch_snapshot_repository.rb │ │ ├── elasticsearch_template.rb │ │ ├── elasticsearch_user.rb │ │ ├── elasticsearch_user_file.rb │ │ ├── elasticsearch_user_roles.rb │ │ └── es_instance_conn_validator.rb │ └── util │ │ └── es_instance_validator.rb └── puppet_x │ └── elastic │ ├── asymmetric_compare.rb │ ├── deep_implode.rb │ ├── deep_to_i.rb │ ├── deep_to_s.rb │ ├── elasticsearch_rest_resource.rb │ ├── es_versioning.rb │ ├── hash.rb │ └── plugin_parsing.rb ├── manifests ├── component_template.pp ├── config.pp ├── ilm_policy.pp ├── index.pp ├── index_template.pp ├── init.pp ├── license.pp ├── package.pp ├── pipeline.pp ├── plugin.pp ├── role.pp ├── script.pp ├── service.pp ├── slm_policy.pp ├── snapshot_repository.pp ├── template.pp └── user.pp ├── metadata.json ├── spec ├── acceptance │ └── tests │ │ └── acceptance_spec.rb ├── classes │ ├── 000_elasticsearch_init_spec.rb │ ├── 001_hiera_spec.rb │ ├── 006_elasticsearch_license_spec.rb │ ├── 010_elasticsearch_init_unkown_spec.rb │ └── 099_coverage_spec.rb ├── defines │ ├── 003_elasticsearch_template_spec.rb │ ├── 004_elasticsearch_plugin_spec.rb │ ├── 006_elasticsearch_script_spec.rb │ ├── 007_elasticsearch_user_spec.rb │ ├── 008_elasticsearch_role_spec.rb │ ├── 009_elasticsearch_pipeline_spec.rb │ ├── 012_elasticsearch_index_spec.rb │ ├── 013_elasticsearch_snapshot_repository_spec.rb │ ├── 014_elasticsearch_component_template_spec.rb │ ├── 015_elasticsearch_index_template_spec.rb │ ├── 016_elasticsearch_ilm_policy_spec.rb │ └── 017_elasticsearch_slm_policy_spec.rb ├── fixtures │ ├── artifacts │ │ ├── .gitkeep │ │ └── plugins │ │ │ └── .gitkeep │ ├── data │ │ ├── common.yaml │ │ ├── composabletemplate.yaml │ │ ├── envs │ │ │ ├── defaultinstance-merged.yaml │ │ │ └── defaultinstance.yaml │ │ ├── multipleinstances.yaml │ │ ├── singleilmpolicy.yaml │ │ ├── singleindex.yaml │ │ ├── singleinstance.yaml │ │ ├── singlepipeline.yaml │ │ ├── singleplugin.yaml │ │ ├── singlerole.yaml │ │ ├── singlescript.yaml │ │ ├── singleslmpolicy.yaml │ │ ├── singletemplate.yaml │ │ └── singleuser.yaml │ ├── facts │ │ ├── Warlock-nodes.json │ │ ├── Warlock-root.json │ │ ├── Zom-nodes.json │ │ └── Zom-root.json │ ├── hiera.yaml │ ├── ilm_policies │ │ └── example.json │ ├── pipelines │ │ └── example.json │ ├── slm_policies │ │ └── example.json │ └── templates │ │ ├── 6.x.json │ │ ├── 7.x.json │ │ ├── component.json │ │ ├── index.json │ │ └── post_8.0.json ├── functions │ ├── concat_merge_spec.rb │ ├── deep_implode_spec.rb │ ├── es_plugin_name_spec.rb │ └── plugin_dir_spec.rb ├── helpers │ ├── acceptance │ │ └── tests │ │ │ ├── bad_manifest_shared_examples.rb │ │ │ ├── basic_shared_examples.rb │ │ │ ├── component_template_shared_examples.rb │ │ │ ├── datadir_shared_examples.rb │ │ │ ├── hiera_shared_examples.rb │ │ │ ├── ilm_policy_shared_examples.rb │ │ │ ├── index_template_shared_examples.rb │ │ │ ├── manifest_shared_examples.rb │ │ │ ├── package_url_shared_examples.rb │ │ │ ├── pipeline_shared_examples.rb │ │ │ ├── plugin_api_shared_examples.rb │ │ │ ├── plugin_shared_examples.rb │ │ │ ├── plugin_upgrade_shared_examples.rb │ │ │ ├── removal_shared_examples.rb │ │ │ ├── security_shared_examples.rb │ │ │ ├── slm_policy_shared_examples.rb │ │ │ ├── snapshot_repository_shared_examples.rb │ │ │ ├── template_shared_examples.rb │ │ │ └── usergroup_shared_examples.rb │ ├── class_shared_examples.rb │ └── unit │ │ ├── provider │ │ └── elasticsearch_rest_shared_examples.rb │ │ └── type │ │ └── elasticsearch_rest_shared_examples.rb ├── matrix.yml ├── setup_acceptance_node.pp ├── spec_helper.rb ├── spec_helper_acceptance.rb ├── spec_helper_rspec.rb ├── spec_helper_tls.rb ├── spec_utilities.rb ├── support │ └── acceptance │ │ └── elastic.rb ├── templates │ ├── 001_elasticsearch.yml.erb_spec.rb │ └── 002_jvm.options.erb_spec.rb └── unit │ ├── facter │ └── es_facts_spec.rb │ ├── provider │ ├── elastic_parsedfile_spec.rb │ ├── elastic_yaml_spec.rb │ ├── elasticsearch_component_template │ │ └── ruby_spec.rb │ ├── elasticsearch_ilm_policy │ │ └── ruby_spec.rb │ ├── elasticsearch_index │ │ └── ruby_spec.rb │ ├── elasticsearch_index_template │ │ └── ruby_spec.rb │ ├── elasticsearch_keystore │ │ └── elasticsearch_keystore_spec.rb │ ├── elasticsearch_license │ │ └── xpack_spec.rb │ ├── elasticsearch_pipeline │ │ └── ruby_spec.rb │ ├── elasticsearch_plugin │ │ ├── ruby_spec.rb │ │ └── shared_examples.rb │ ├── elasticsearch_role │ │ └── ruby_spec.rb │ ├── elasticsearch_role_mapping │ │ └── ruby_spec.rb │ ├── elasticsearch_slm_policy │ │ └── ruby_spec.rb │ ├── elasticsearch_snapshot_repository │ │ └── ruby_spec.rb │ ├── elasticsearch_template │ │ └── ruby_spec.rb │ ├── elasticsearch_user │ │ └── ruby_spec.rb │ ├── elasticsearch_user_file │ │ └── ruby_spec.rb │ └── elasticsearch_user_roles │ │ └── ruby_spec.rb │ ├── puppet_x │ └── elastic │ │ └── hash_spec.rb │ └── type │ ├── elasticsearch_component_template_spec.rb │ ├── elasticsearch_ilm_policy_spec.rb │ ├── elasticsearch_index_spec.rb │ ├── elasticsearch_index_template_spec.rb │ ├── elasticsearch_keystore_spec.rb │ ├── elasticsearch_license_spec.rb │ ├── elasticsearch_pipeline_spec.rb │ ├── elasticsearch_plugin_spec.rb │ ├── elasticsearch_role_mapping_spec.rb │ ├── elasticsearch_role_spec.rb │ ├── elasticsearch_slm_policy_spec.rb │ ├── elasticsearch_snapshot_repository_spec.rb │ ├── elasticsearch_template_spec.rb │ ├── elasticsearch_user_roles_spec.rb │ ├── elasticsearch_user_spec.rb │ └── es_instance_conn_validator_spec.rb ├── templates ├── etc │ ├── elasticsearch │ │ ├── elasticsearch.yml.erb │ │ ├── jvm.options.d │ │ │ └── jvm.options.epp │ │ └── log4j2.properties.erb │ └── sysconfig │ │ └── defaults.erb └── usr │ └── lib │ └── tmpfiles.d │ └── elasticsearch.conf.erb └── types ├── multipath.pp └── status.pp /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | root = true 7 | 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | indent_size = 2 12 | tab_width = 2 13 | indent_style = space 14 | insert_final_newline = true 15 | trim_trailing_whitespace = true 16 | -------------------------------------------------------------------------------- /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | repositories: 3 | apt: https://github.com/puppetlabs/puppetlabs-apt.git 4 | archive: https://github.com/voxpupuli/puppet-archive.git 5 | augeas_core: https://github.com/puppetlabs/puppetlabs-augeas_core.git 6 | concat: https://github.com/puppetlabs/puppetlabs-concat.git 7 | elastic_stack: https://github.com/voxpupuli/puppet-elastic_stack.git 8 | java: https://github.com/puppetlabs/puppetlabs-java.git 9 | java_ks: https://github.com/puppetlabs/puppetlabs-java_ks.git 10 | stdlib: https://github.com/puppetlabs/puppetlabs-stdlib.git 11 | yumrepo_core: https://github.com/puppetlabs/puppetlabs-yumrepo_core.git 12 | zypprepo: https://github.com/voxpupuli/puppet-zypprepo.git 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /CHANGELOG.md merge=union 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ## Affected Puppet, Ruby, OS and module versions/distributions 12 | 13 | - Puppet: 14 | - Ruby: 15 | - Distribution: 16 | - Module version: 17 | 18 | ## How to reproduce (e.g Puppet code you use) 19 | 20 | ## What are you seeing 21 | 22 | ## What behaviour did you expect instead 23 | 24 | ## Output log 25 | 26 | ## Any additional information you'd like to impart 27 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 9 | #### Pull Request (PR) description 10 | 13 | 14 | #### This Pull Request (PR) fixes the following issues 15 | 21 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | skip-changelog: 6 | - head-branch: ['^release-*', 'release'] 7 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | # https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes 6 | 7 | changelog: 8 | exclude: 9 | labels: 10 | - duplicate 11 | - invalid 12 | - modulesync 13 | - question 14 | - skip-changelog 15 | - wont-fix 16 | - wontfix 17 | 18 | categories: 19 | - title: Breaking Changes 🛠 20 | labels: 21 | - backwards-incompatible 22 | 23 | - title: New Features 🎉 24 | labels: 25 | - enhancement 26 | 27 | - title: Bug Fixes 🐛 28 | labels: 29 | - bug 30 | 31 | - title: Documentation Updates 📚 32 | labels: 33 | - documentation 34 | - docs 35 | 36 | - title: Dependency Updates ⬆️ 37 | labels: 38 | - dependencies 39 | 40 | - title: Other Changes 41 | labels: 42 | - "*" 43 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: CI 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | pull_request: {} 10 | push: 11 | branches: 12 | - main 13 | - master 14 | 15 | concurrency: 16 | group: ${{ github.ref_name }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | puppet: 21 | name: Puppet 22 | uses: voxpupuli/gha-puppet/.github/workflows/beaker.yml@v3 23 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: "Pull Request Labeler" 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | pull_request_target: {} 10 | 11 | jobs: 12 | labeler: 13 | permissions: 14 | contents: read 15 | pull-requests: write 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/labeler@v5 19 | -------------------------------------------------------------------------------- /.github/workflows/prepare_release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: 'Prepare Release' 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | version: 11 | description: 'Module version to be released. Must be a valid semver string without leading v. (1.2.3)' 12 | required: false 13 | 14 | jobs: 15 | release_prep: 16 | uses: 'voxpupuli/gha-puppet/.github/workflows/prepare_release.yml@v3' 17 | with: 18 | version: ${{ github.event.inputs.version }} 19 | allowed_owner: 'voxpupuli' 20 | secrets: 21 | # Configure secrets here: 22 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 23 | github_pat: '${{ secrets.PCCI_PAT_RELEASE_PREP }}' 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: Release 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | push: 10 | tags: 11 | - '*' 12 | 13 | jobs: 14 | release: 15 | name: Release 16 | uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v3 17 | with: 18 | allowed_owner: 'voxpupuli' 19 | secrets: 20 | # Configure secrets here: 21 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 22 | username: ${{ secrets.PUPPET_FORGE_USERNAME }} 23 | api_key: ${{ secrets.PUPPET_FORGE_API_KEY }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | /pkg/ 5 | /Gemfile.lock 6 | /Gemfile.local 7 | /vendor/ 8 | /.vendor/ 9 | /spec/fixtures/manifests/ 10 | /spec/fixtures/modules/ 11 | /.vagrant/ 12 | /.bundle/ 13 | /.ruby-version 14 | /coverage/ 15 | /log/ 16 | /.idea/ 17 | /.dependencies/ 18 | /.librarian/ 19 | /Puppetfile.lock 20 | *.iml 21 | .*.sw? 22 | /.yardoc/ 23 | /Guardfile 24 | bolt-debug.log 25 | .rerun.json 26 | -------------------------------------------------------------------------------- /.msync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | modulesync_config_version: '9.7.0' 6 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | # 4 | # Hooks are only enabled if you take action. 5 | # 6 | # To enable the hooks run: 7 | # 8 | # ``` 9 | # bundle exec overcommit --install 10 | # # ensure .overcommit.yml does not harm to you and then 11 | # bundle exec overcommit --sign 12 | # ``` 13 | # 14 | # (it will manage the .git/hooks directory): 15 | # 16 | # Examples howto skip a test for a commit or push: 17 | # 18 | # ``` 19 | # SKIP=RuboCop git commit 20 | # SKIP=PuppetLint git commit 21 | # SKIP=RakeTask git push 22 | # ``` 23 | # 24 | # Don't invoke overcommit at all: 25 | # 26 | # ``` 27 | # OVERCOMMIT_DISABLE=1 git commit 28 | # ``` 29 | # 30 | # Read more about overcommit: https://github.com/brigade/overcommit 31 | # 32 | # To manage this config yourself in your module add 33 | # 34 | # ``` 35 | # .overcommit.yml: 36 | # unmanaged: true 37 | # ``` 38 | # 39 | # to your modules .sync.yml config 40 | --- 41 | PreCommit: 42 | RuboCop: 43 | enabled: true 44 | description: 'Runs rubocop on modified files only' 45 | command: ['bundle', 'exec', 'rubocop'] 46 | RakeTarget: 47 | enabled: true 48 | description: 'Runs lint on modified files only' 49 | targets: 50 | - 'lint' 51 | command: ['bundle', 'exec', 'rake'] 52 | YamlSyntax: 53 | enabled: true 54 | JsonSyntax: 55 | enabled: true 56 | TrailingWhitespace: 57 | enabled: true 58 | 59 | PrePush: 60 | RakeTarget: 61 | enabled: true 62 | description: 'Run rake targets' 63 | targets: 64 | - 'validate' 65 | - 'test' 66 | - 'rubocop' 67 | command: ['bundle', 'exec', 'rake'] 68 | -------------------------------------------------------------------------------- /.pmtignore: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | /docs/ 5 | /pkg/ 6 | /Gemfile 7 | /Gemfile.lock 8 | /Gemfile.local 9 | /vendor/ 10 | /.vendor/ 11 | /spec/ 12 | /Rakefile 13 | /.vagrant/ 14 | /.bundle/ 15 | /.ruby-version 16 | /coverage/ 17 | /log/ 18 | /.idea/ 19 | /.dependencies/ 20 | /.github/ 21 | /.librarian/ 22 | /Puppetfile.lock 23 | /Puppetfile 24 | *.iml 25 | /.editorconfig 26 | /.fixtures.yml 27 | /.gitignore 28 | /.msync.yml 29 | /.overcommit.yml 30 | /.pmtignore 31 | /.rspec 32 | /.rspec_parallel 33 | /.rubocop.yml 34 | /.sync.yml 35 | .*.sw? 36 | /.yardoc/ 37 | /.yardopts 38 | /Dockerfile 39 | /HISTORY.md 40 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | --fail-on-warnings 5 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | inherit_from: .rubocop_todo.yml 6 | inherit_gem: 7 | voxpupuli-test: rubocop.yml 8 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2024-02-11 16:22:05 UTC using RuboCop version 1.50.2. 4 | # The point is for the user to remove these configuration records 5 | # one by one as the offenses are removed from the code base. 6 | # Note that changes in the inspected code, or installation of new 7 | # versions of RuboCop, may require this file to be generated again. 8 | 9 | # Offense count: 32 10 | # Configuration parameters: Max. 11 | RSpec/IndexedLet: 12 | Exclude: 13 | - 'spec/unit/provider/elasticsearch_component_template/ruby_spec.rb' 14 | - 'spec/unit/provider/elasticsearch_ilm_policy/ruby_spec.rb' 15 | - 'spec/unit/provider/elasticsearch_index/ruby_spec.rb' 16 | - 'spec/unit/provider/elasticsearch_index_template/ruby_spec.rb' 17 | - 'spec/unit/provider/elasticsearch_pipeline/ruby_spec.rb' 18 | - 'spec/unit/provider/elasticsearch_slm_policy/ruby_spec.rb' 19 | - 'spec/unit/provider/elasticsearch_snapshot_repository/ruby_spec.rb' 20 | - 'spec/unit/provider/elasticsearch_template/ruby_spec.rb' 21 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | .puppet-lint.rc: 3 | enabled_lint_checks: 4 | - parameter_documentation 5 | - parameter_types 6 | Gemfile: 7 | optional: 8 | ':test': 9 | - gem: bcrypt 10 | - gem: webmock 11 | ':system_tests': 12 | - gem: bcrypt 13 | - gem: rspec-retry 14 | - gem: simp-beaker-helpers 15 | spec/spec_helper.rb: 16 | hiera_config: "'spec/fixtures/hiera.yaml'" 17 | spec/spec_helper_acceptance.rb: 18 | unmanaged: false 19 | -------------------------------------------------------------------------------- /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 | * Elastic (elastic) 6 | 7 | Contributors: 8 | Tyler Langlois (tylerjl) 9 | Richard Pijnenburg (electrical) 10 | Martin Seener (martinseener) 11 | Marcus Furlong (furlongm) 12 | Chris Boulton (chrisboulton) 13 | Igor Galić (igalic) 14 | Vincent Janelle (vjanelle) 15 | Mathieu Bornoz (mbornoz) 16 | Justin Lambert (jlambert121) 17 | Brian Lalor (blalor) 18 | Stas Alekseev (salekseev) 19 | Simon Effenberg (Savar) 20 | Bruce Morrison (brucem) 21 | deanmalmgren 22 | Matteo Sessa (msessa-cotd) 23 | Sebastian Reitenbach (buzzdeee) 24 | Toni Schmidbauer (tosmi) 25 | Dan Sajner (dansajner) 26 | Leo Antunes (costela) 27 | Philip Wigg (philipwigg) 28 | Ian Bissett (bisscuitt) 29 | Fabian M. Krack (onibox) 30 | Rhommel Lamas (rhoml) 31 | Jose Luis Ledesma (sp-joseluis-ledesma) 32 | Matthias Baur (baurmatt) 33 | Gavin Williams (fatmcgav) 34 | Giedrius Statkevičius (GiedriusS) 35 | Jakub Pieńkowski (Jakski) 36 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | source ENV['GEM_SOURCE'] || 'https://rubygems.org' 5 | 6 | group :test do 7 | gem 'voxpupuli-test', '~> 10.0', :require => false 8 | gem 'puppet_metadata', '~> 5.0', :require => false 9 | gem 'bcrypt', :require => false 10 | gem 'webmock', :require => false 11 | end 12 | 13 | group :development do 14 | gem 'guard-rake', :require => false 15 | gem 'overcommit', '>= 0.39.1', :require => false 16 | end 17 | 18 | group :system_tests do 19 | gem 'voxpupuli-acceptance', '~> 3.5', :require => false 20 | gem 'bcrypt', :require => false 21 | gem 'rspec-retry', :require => false 22 | gem 'simp-beaker-helpers', :require => false 23 | end 24 | 25 | group :release do 26 | gem 'voxpupuli-release', '~> 3.0', :require => false 27 | end 28 | 29 | gem 'rake', :require => false 30 | gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] 31 | 32 | puppetversion = ENV['PUPPET_GEM_VERSION'] || [">= 7.24", "< 9"] 33 | gem 'puppet', puppetversion, :require => false, :groups => [:test] 34 | 35 | # vim: syntax=ruby 36 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | # Attempt to load voxpupuli-test (which pulls in puppetlabs_spec_helper), 5 | # otherwise attempt to load it directly. 6 | begin 7 | require 'voxpupuli/test/rake' 8 | rescue LoadError 9 | begin 10 | require 'puppetlabs_spec_helper/rake_tasks' 11 | rescue LoadError 12 | end 13 | end 14 | 15 | # load optional tasks for acceptance 16 | # only available if gem group releases is installed 17 | begin 18 | require 'voxpupuli/acceptance/rake' 19 | rescue LoadError 20 | end 21 | 22 | # load optional tasks for releases 23 | # only available if gem group releases is installed 24 | begin 25 | require 'voxpupuli/release/rake_tasks' 26 | rescue LoadError 27 | # voxpupuli-release not present 28 | else 29 | GCGConfig.user = 'voxpupuli' 30 | GCGConfig.project = 'puppet-elasticsearch' 31 | end 32 | 33 | desc "Run main 'test' task and report merged results to coveralls" 34 | task test_with_coveralls: [:test] do 35 | if Dir.exist?(File.expand_path('../lib', __FILE__)) 36 | require 'coveralls/rake/task' 37 | Coveralls::RakeTask.new 38 | Rake::Task['coveralls:push'].invoke 39 | else 40 | puts 'Skipping reporting to coveralls. Module has no lib dir' 41 | end 42 | end 43 | 44 | # vim: syntax=ruby 45 | -------------------------------------------------------------------------------- /data/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::api_basic_auth_password: 3 | elasticsearch::api_basic_auth_username: 4 | elasticsearch::api_ca_file: 5 | elasticsearch::api_ca_path: 6 | elasticsearch::api_host: localhost 7 | elasticsearch::api_port: 9200 8 | elasticsearch::api_protocol: http 9 | elasticsearch::api_timeout: 10 10 | elasticsearch::autoupgrade: false 11 | elasticsearch::config: {} 12 | elasticsearch::configdir: "/etc/elasticsearch" 13 | elasticsearch::configdir_recurselimit: 2 14 | elasticsearch::default_logging_level: INFO 15 | elasticsearch::daily_rolling_date_pattern: | 16 | "'.'yyyy-MM-dd" 17 | elasticsearch::defaults_location: 18 | elasticsearch::deprecation_logging: false 19 | elasticsearch::deprecation_logging_level: DEBUG 20 | elasticsearch::download_tool: 21 | elasticsearch::download_tool_insecure: 22 | elasticsearch::download_tool_verify_certificates: true 23 | elasticsearch::ensure: present 24 | elasticsearch::file_rolling_type: dailyRollingFile 25 | elasticsearch::indices: {} 26 | elasticsearch::init_defaults: {} 27 | elasticsearch::init_defaults_file: 28 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.systemd.erb" 29 | elasticsearch::instances: {} 30 | elasticsearch::jvm_options: [] 31 | elasticsearch::license: 32 | elasticsearch::logdir: "/var/log/elasticsearch" 33 | elasticsearch::logging_config: {} 34 | elasticsearch::logging_file: 35 | elasticsearch::logging_level: INFO 36 | elasticsearch::logging_template: 37 | elasticsearch::manage_datadir: true 38 | elasticsearch::manage_logdir: true 39 | elasticsearch::manage_repo: true 40 | elasticsearch::oss: false 41 | elasticsearch::package_dl_timeout: 600 42 | elasticsearch::package_name: elasticsearch 43 | elasticsearch::package_provider: package 44 | elasticsearch::package_url: 45 | elasticsearch::pid_dir: "/var/run/elasticsearch" 46 | elasticsearch::pipelines: {} 47 | elasticsearch::plugindir: 48 | elasticsearch::plugins: {} 49 | elasticsearch::proxy_url: 50 | elasticsearch::purge_configdir: false 51 | elasticsearch::purge_package_dir: false 52 | elasticsearch::purge_secrets: false 53 | elasticsearch::repo_stage: false 54 | elasticsearch::restart_on_change: false 55 | elasticsearch::roles: {} 56 | elasticsearch::rolling_file_max_backup_index: 1 57 | elasticsearch::rolling_file_max_file_size: 10MB 58 | elasticsearch::scripts: {} 59 | elasticsearch::secrets: 60 | elasticsearch::security_logging_content: 61 | elasticsearch::security_logging_source: 62 | elasticsearch::service_name: elasticsearch 63 | elasticsearch::service_provider: systemd 64 | elasticsearch::snapshot_repositories: {} 65 | elasticsearch::ssl: false 66 | elasticsearch::status: enabled 67 | elasticsearch::system_key: 68 | elasticsearch::systemd_service_path: "/lib/systemd/system" 69 | elasticsearch::templates: {} 70 | elasticsearch::users: {} 71 | elasticsearch::validate_tls: true 72 | elasticsearch::version: false 73 | -------------------------------------------------------------------------------- /data/distro/Amazon.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.RedHat.erb" 3 | elasticsearch::service_provider: init 4 | -------------------------------------------------------------------------------- /data/distro/Amazon/2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.systemd.erb" 3 | elasticsearch::service_provider: systemd 4 | -------------------------------------------------------------------------------- /data/distro/Debian/7.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.Debian.erb" 3 | elasticsearch::pid_dir: 4 | elasticsearch::service_provider: init 5 | -------------------------------------------------------------------------------- /data/distro/Ubuntu/12.04.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.Debian.erb" 3 | elasticsearch::pid_dir: 4 | elasticsearch::service_provider: init 5 | -------------------------------------------------------------------------------- /data/distro/Ubuntu/14.04.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.Debian.erb" 3 | elasticsearch::pid_dir: 4 | elasticsearch::service_provider: init 5 | -------------------------------------------------------------------------------- /data/kernel/Darwin.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::download_tool: curl -o 3 | elasticsearch::download_tool_insecure: curl --insecure -o 4 | elasticsearch::elasticsearch_group: elasticsearch 5 | elasticsearch::elasticsearch_user: elasticsearch 6 | -------------------------------------------------------------------------------- /data/kernel/Linux.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::datadir: "/var/lib/elasticsearch" 3 | elasticsearch::download_tool: wget -O 4 | elasticsearch::download_tool_insecure: wget --no-check-certificate -O 5 | elasticsearch::elasticsearch_group: elasticsearch 6 | elasticsearch::elasticsearch_user: elasticsearch 7 | elasticsearch::homedir: "/usr/share/elasticsearch" 8 | elasticsearch::package_dir: "/opt/elasticsearch/swdl" 9 | -------------------------------------------------------------------------------- /data/kernel/OpenBSD.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::datadir: "/var/elasticsearch/data" 3 | elasticsearch::download_tool: ftp -o 4 | elasticsearch::elasticsearch_group: _elasticsearch 5 | elasticsearch::elasticsearch_user: _elasticsearch 6 | elasticsearch::homedir: "/usr/local/elasticsearch" 7 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.OpenBSD.erb" 8 | elasticsearch::manage_repo: false 9 | elasticsearch::package_dir: "/var/cache/elasticsearch" 10 | elasticsearch::service_provider: openbsd 11 | -------------------------------------------------------------------------------- /data/os/Debian.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::defaults_location: "/etc/default" 3 | -------------------------------------------------------------------------------- /data/os/Gentoo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::defaults_location: "/etc/conf.d" 3 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.openrc.erb" 4 | elasticsearch::package_name: app-misc/elasticsearch 5 | elasticsearch::pid_dir: "/run/elasticsearch" 6 | elasticsearch::service_provider: openrc 7 | -------------------------------------------------------------------------------- /data/os/RedHat.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::defaults_location: "/etc/sysconfig" 3 | -------------------------------------------------------------------------------- /data/os/RedHat/5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.RedHat.erb" 3 | elasticsearch::service_provider: init 4 | -------------------------------------------------------------------------------- /data/os/RedHat/6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.RedHat.erb" 3 | elasticsearch::service_provider: init 4 | -------------------------------------------------------------------------------- /data/os/Suse.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::defaults_location: "/etc/sysconfig" 3 | elasticsearch::systemd_service_path: "/usr/lib/systemd/system" 4 | -------------------------------------------------------------------------------- /data/os/Suse/11.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::init_template: "%{module_name}/etc/init.d/elasticsearch.SLES.erb" 3 | elasticsearch::pid_dir: 4 | elasticsearch::service_provider: init 5 | -------------------------------------------------------------------------------- /files/etc/init.d/elasticsearch.OpenBSD.erb: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This file is managed via PUPPET 4 | 5 | daemon="/usr/local/elasticsearch/bin/elasticsearch" 6 | daemon_flags="-d -<%= opt_flag %>default.path.conf=/etc/elasticsearch/<%= @resource[:instance] %> -p <%= @resource[:pid_dir] %>/elasticsearch-<%= @resource[:instance] %>.pid" 7 | daemon_user="_elasticsearch" 8 | 9 | . /etc/rc.d/rc.subr 10 | 11 | pexp="$(/usr/local/bin/javaPathHelper -c elasticsearch) .*org.elasticsearch.bootstrap.Elasticsearch.*" 12 | 13 | rc_reload=NO 14 | 15 | rc_start() { 16 | ${rcexec} \ 17 | "ES_INCLUDE=\"/etc/elasticsearch/elasticsearch.in.sh\" \ 18 | "ES_JVM_OPTIONS=\"/etc/elasticsearch/<%= @resource[:instance] %>/jvm.options\"" \ 19 | JAVA_HOME=\"$(/usr/local/bin/javaPathHelper -h elasticsearch)\" \ 20 | ${daemon} ${daemon_flags}" 21 | } 22 | 23 | rc_pre() { 24 | install -d -o _elasticsearch <%= @resource[:pid_dir] %> 25 | } 26 | 27 | rc_cmd $1 28 | -------------------------------------------------------------------------------- /files/etc/init.d/elasticsearch.openrc.erb: -------------------------------------------------------------------------------- 1 | #!/sbin/runscript 2 | 3 | name="Elasticsearch" 4 | description="" 5 | 6 | ES_USER=${ES_USER:="elasticsearch"} 7 | ES_INSTANCE=${SVCNAME#*.} 8 | 9 | if [ -n "${ES_INSTANCE}" ] && [ ${SVCNAME} != "elasticsearch" ]; then 10 | PIDFILE="/run/elasticsearch/elasticsearch.${ES_INSTANCE}.pid" 11 | ES_HOME="/var/lib/elasticsearch/${ES_INSTANCE}" 12 | CONF_DIR="/etc/elasticsearch/${ES_INSTANCE}" 13 | LOG_DIR="/var/log/elasticsearch/${ES_INSTANCE}" 14 | else 15 | PIDFILE="/run/elasticsearch/elasticsearch.pid" 16 | ES_HOME="/var/lib/elasticsearch/_default" 17 | CONF_DIR="/etc/elasticsearch" 18 | LOG_DIR="/var/log/elasticsearch/_default" 19 | fi 20 | 21 | DATA_DIR="${ES_HOME}/data" 22 | WORK_DIR="${ES_HOME}/work" 23 | MAX_MAP_COUNT=262144 24 | 25 | export ES_INCLUDE="/usr/share/elasticsearch/bin/elasticsearch.in.sh" 26 | export JAVA_OPTS 27 | export ES_JAVA_OPTS 28 | export ES_JVM_OPTIONS 29 | export ES_HEAP_SIZE 30 | export ES_HEAP_NEWSIZE 31 | export ES_DIRECT_SIZE 32 | export ES_USE_IPV4 33 | 34 | server_command="/usr/share/elasticsearch/bin/elasticsearch" 35 | server_args=" -p ${PIDFILE} <%= opt_flags.join(' ') %>" 36 | 37 | depend() { 38 | use net 39 | } 40 | 41 | start() { 42 | [ ! -f "${ES_INCLUDE}" ] && { 43 | eerror "${ES_INCLUDE} must be copied into place" 44 | return 1 45 | } 46 | 47 | local conf 48 | local conf_file 49 | for conf in elasticsearch.yml logging.yml; do 50 | conf_file="${CONF_DIR}/${conf}" 51 | if [ ! -f "${conf_file}" ]; then 52 | eerror "${conf_file} must be copied into place" 53 | return 1 54 | fi 55 | done 56 | 57 | ebegin "Starting ${SVCNAME}" 58 | 59 | if [ -n "${ES_MAX_FD}" ]; then 60 | ulimit -n ${ES_MAX_FD} 61 | einfo "Max open filedescriptors : ${ES_MAX_FD}" 62 | fi 63 | 64 | if [ -n "${MAX_MAP_COUNT}" -a -f /proc/sys/vm/max_map_count ]; then 65 | sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT 66 | fi 67 | 68 | checkpath -d -o "${ES_USER}" -m750 "/var/lib/elasticsearch" 69 | checkpath -d -o "${ES_USER}" -m750 "/var/log/elasticsearch" 70 | checkpath -d -o "${ES_USER}" -m750 "$(dirname "${PIDFILE}")" 71 | checkpath -d -o "${ES_USER}" -m750 "${ES_HOME}" 72 | checkpath -d -o "${ES_USER}" -m750 "${LOG_DIR}" 73 | 74 | start-stop-daemon --start \ 75 | --background \ 76 | --chdir "${ES_HOME}" \ 77 | --user="${ES_USER}" \ 78 | --pidfile="${PIDFILE}" \ 79 | --exec ${server_command} -- ${server_args} 80 | eend $? 81 | } 82 | 83 | stop() { 84 | ebegin "Stopping ${SVCNAME}" 85 | start-stop-daemon --stop \ 86 | --pidfile=${PIDFILE} \ 87 | --user="${ES_USER}" \ 88 | --retry=TERM/20/KILL/5 89 | eend $? 90 | } 91 | -------------------------------------------------------------------------------- /files/etc/init.d/elasticsearch.systemd.erb: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Elasticsearch instance <%= @resource[:instance] %> 3 | Documentation=http://www.elastic.co 4 | Wants=network-online.target 5 | After=network-online.target 6 | 7 | [Service] 8 | EnvironmentFile=<%= @resource[:defaults_location] %>/elasticsearch-<%= @resource[:instance] %> 9 | 10 | WorkingDirectory=<%= @resource[:homedir] %> 11 | 12 | User=<%= @resource[:user] %> 13 | Group=<%= @resource[:group] %> 14 | 15 | ExecStart=/usr/share/elasticsearch/bin/elasticsearch \ 16 | -p <%= @resource[:pid_dir] %>/elasticsearch-<%= @resource[:instance] %>.pid \ 17 | <%= opt_flags.join(' ') %> 18 | 19 | # StandardOutput is configured to redirect to journalctl since 20 | # some error messages may be logged in standard output before 21 | # elasticsearch logging system is initialized. Elasticsearch 22 | # stores its logs in /var/log/elasticsearch and does not use 23 | # journalctl by default. If you also want to enable journalctl 24 | # logging, you can simply remove the "quiet" option from ExecStart. 25 | StandardOutput=journal 26 | StandardError=inherit 27 | 28 | # Specifies the maximum file descriptor number that can be opened by this process 29 | LimitNOFILE=<%= @resource[:nofile] %> 30 | 31 | # Specifies the maximum number of processes 32 | LimitNPROC=<%= @resource[:nproc] %> 33 | 34 | # Specifies the maximum number of bytes of memory that may be locked into RAM 35 | # Set to "infinity" if you use the 'bootstrap.memory_lock: true' option 36 | # in elasticsearch.yml and 'MAX_LOCKED_MEMORY=unlimited' in ${path.env} 37 | #LimitMEMLOCK=infinity 38 | <% if @resource[:memlock] == 'unlimited' %> 39 | LimitMEMLOCK=infinity 40 | <% elsif @resource[:memlock] %> 41 | LimitMEMLOCK=<%= @resource[:memlock] %> 42 | <% end %> 43 | 44 | # Disable timeout logic and wait until process is stopped 45 | TimeoutStopSec=0 46 | 47 | # SIGTERM signal is used to stop the Java process 48 | KillSignal=SIGTERM 49 | 50 | # Send the signal only to the JVM rather than its control group 51 | KillMode=process 52 | 53 | # Java process is never killed 54 | SendSIGKILL=no 55 | 56 | # When a JVM receives a SIGTERM signal it exits with code 143 57 | SuccessExitStatus=143 58 | 59 | [Install] 60 | WantedBy=multi-user.target 61 | -------------------------------------------------------------------------------- /hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 5 3 | defaults: 4 | datadir: data 5 | data_hash: yaml_data 6 | hierarchy: 7 | - name: Distribution major version 8 | path: distro/%{facts.os.name}/%{facts.os.release.major}.yaml 9 | - name: Operating system family major version 10 | path: os/%{facts.os.family}/%{facts.os.release.major}.yaml 11 | - name: Distribution name 12 | path: distro/%{facts.os.name}.yaml 13 | - name: Operating system family 14 | path: os/%{facts.os.family}.yaml 15 | - name: System kernel 16 | path: kernel/%{facts.kernel}.yaml 17 | - name: Default values 18 | path: common.yaml 19 | -------------------------------------------------------------------------------- /lib/puppet/feature/elasticsearch_shield_users_native.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/util/feature' 4 | require 'puppet/util/package' 5 | 6 | shield_plugin_dir = '/usr/share/elasticsearch/plugins/shield' 7 | 8 | Puppet.features.add(:elasticsearch_shield_users_native) do 9 | return false unless File.exist?(shield_plugin_dir) 10 | 11 | jars = Dir["#{shield_plugin_dir}/*.jar"] 12 | jar_parts = jars.map do |file| 13 | File.basename(file, '.jar').split('-') 14 | end 15 | shield_components = jar_parts.select do |parts| 16 | parts.include? 'shield' 17 | end 18 | shield_components.any? do |parts| 19 | parts.last =~ %r{^[\d.]+$} && 20 | Puppet::Util::Package.versioncmp(parts.last, '2.3') >= 0 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/array_suffix.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Top-level Puppet functions 4 | module Puppet::Parser::Functions 5 | newfunction( 6 | :array_suffix, 7 | type: :rvalue, 8 | doc: <<~EOS 9 | This function applies a suffix to all elements in an array. 10 | 11 | *Examples:* 12 | 13 | array_suffix(['a','b','c'], 'p') 14 | 15 | Will return: ['ap','bp','cp'] 16 | 17 | @return Array 18 | EOS 19 | ) do |arguments| 20 | # Technically we support two arguments but only first is mandatory ... 21 | if arguments.empty? 22 | raise(Puppet::ParseError, 'array_suffix(): Wrong number of arguments ' \ 23 | "given (#{arguments.size} for 1)") 24 | end 25 | 26 | array = arguments[0] 27 | 28 | raise Puppet::ParseError, "array_suffix(): expected first argument to be an Array, got #{array.inspect}" unless array.is_a?(Array) 29 | 30 | suffix = arguments[1] if arguments[1] 31 | 32 | raise Puppet::ParseError, "array_suffix(): expected second argument to be a String, got #{suffix.inspect}" if suffix && !(suffix.is_a? String) 33 | 34 | # Turn everything into string same as join would do ... 35 | result = array.map do |i| 36 | i = i.to_s 37 | suffix ? i + suffix : i 38 | end 39 | 40 | return result 41 | end 42 | end 43 | 44 | # vim: set ts=2 sw=2 et : 45 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/concat_merge.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Top-level Puppet functions 4 | module Puppet::Parser::Functions 5 | newfunction( 6 | :concat_merge, 7 | type: :rvalue, 8 | doc: <<-ENDHEREDOC) do |args| 9 | Merges two or more hashes together concatenating duplicate keys 10 | with array values and returns the resulting hash. 11 | 12 | For example: 13 | 14 | $hash1 = {'a' => [1]} 15 | $hash2 = {'a' => [2]} 16 | concat_merge($hash1, $hash2) 17 | # The resulting hash is equivalent to: 18 | # { 'a' => [1, 2] } 19 | 20 | When there is a duplicate key that is not an array, the key in 21 | the rightmost hash will "win." 22 | 23 | @return String 24 | ENDHEREDOC 25 | 26 | raise Puppet::ParseError, "concat_merge(): wrong number of arguments (#{args.length}; must be at least 2)" if args.length < 2 27 | 28 | concat_merge = proc do |hash1, hash2| 29 | hash1.merge(hash2) do |_key, old_value, new_value| 30 | if old_value.is_a?(Array) && new_value.is_a?(Array) 31 | old_value + new_value 32 | else 33 | new_value 34 | end 35 | end 36 | end 37 | 38 | result = {} 39 | args.each do |arg| 40 | next if arg.is_a?(String) && arg.empty? # empty string is synonym for puppet's undef 41 | # If the argument was not a hash, skip it. 42 | raise Puppet::ParseError, "concat_merge: unexpected argument type #{arg.class}, only expects hash arguments" unless arg.is_a?(Hash) 43 | 44 | result = concat_merge.call(result, arg) 45 | end 46 | result 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/deep_implode.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet_x/elastic/deep_implode' 6 | 7 | # Top-level Puppet functions 8 | module Puppet::Parser::Functions 9 | newfunction( 10 | :deep_implode, 11 | type: :rvalue, 12 | doc: <<-ENDHEREDOC) do |args| 13 | Recursively flattens all keys of a hash into a dot-notated 14 | hash, deeply merging duplicate key values by natively combining 15 | them and returns the resulting hash. 16 | 17 | That is confusing, look at the examples for more clarity. 18 | 19 | For example: 20 | 21 | $hash = {'top' => {'sub' => [1]}, 'top.sub' => [2] } 22 | $flattened_hash = deep_implode($hash) 23 | # The resulting hash is equivalent to: 24 | # { 'top.sub' => [1, 2] } 25 | 26 | When the function encounters array or hash values, they are 27 | concatenated or merged, respectively. 28 | When duplace paths for a key are generated, the function will prefer 29 | to retain keys with the longest root key. 30 | 31 | @return Hash 32 | ENDHEREDOC 33 | 34 | raise Puppet::ParseError, "deep_implode(): wrong number of arguments (#{args.length}; must be 1)" if args.length != 1 35 | 36 | arg = args[0] 37 | 38 | raise Puppet::ParseError, 'deep_implode: unexpected argument type, only expects hashes' unless arg.is_a? Hash 39 | 40 | return {} if arg.empty? 41 | 42 | Puppet_X::Elastic.deep_implode arg 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/es_plugin_name.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet_x/elastic/plugin_parsing' 6 | 7 | # Top-level Puppet functions 8 | module Puppet::Parser::Functions 9 | newfunction( 10 | :es_plugin_name, 11 | type: :rvalue, 12 | doc: <<-ENDHEREDOC) do |args| 13 | Given a string, return the best guess at what the directory name 14 | will be for the given plugin. Any arguments past the first will 15 | be fallbacks (using the same logic) should the first fail. 16 | 17 | For example, all the following return values are "plug": 18 | 19 | es_plugin_name('plug') 20 | es_plugin_name('foo/plug') 21 | es_plugin_name('foo/plug/1.0.0') 22 | es_plugin_name('foo/elasticsearch-plug') 23 | es_plugin_name('foo/es-plug/1.3.2') 24 | 25 | @return String 26 | ENDHEREDOC 27 | 28 | if args.empty? 29 | raise Puppet::ParseError, 30 | 'wrong number of arguments, at least one value required' 31 | end 32 | 33 | ret = args.select do |arg| 34 | arg.is_a?(String) && !arg.empty? 35 | end.first 36 | 37 | if ret 38 | Puppet_X::Elastic.plugin_name ret 39 | else 40 | raise Puppet::Error, 41 | 'could not determine plugin name' 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/plugin_dir.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Top-level Puppet functions 4 | module Puppet::Parser::Functions 5 | newfunction( 6 | :plugin_dir, 7 | type: :rvalue, 8 | doc: <<-EOS 9 | Extracts the end plugin directory of the name 10 | 11 | @return String 12 | EOS 13 | ) do |arguments| 14 | raise(Puppet::ParseError, 'plugin_dir(): No arguments given') if arguments.empty? 15 | raise(Puppet::ParseError, "plugin_dir(): Too many arguments given (#{arguments.size})") if arguments.size > 2 16 | raise(Puppet::ParseError, 'plugin_dir(): Requires string as first argument') unless arguments[0].is_a?(String) 17 | 18 | plugin_name = arguments[0] 19 | items = plugin_name.split('/') 20 | 21 | return items[0] if items.count == 1 22 | 23 | plugin = items[1] 24 | endname = if plugin.include?('-') # example elasticsearch-head 25 | if plugin.start_with?('elasticsearch-') 26 | plugin.gsub('elasticsearch-', '') 27 | elsif plugin.start_with?('es-') 28 | plugin.gsub('es-', '') 29 | else 30 | plugin 31 | end 32 | else 33 | plugin 34 | end 35 | 36 | return endname 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/puppet/provider/elastic_parsedfile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/parsedfile' 4 | 5 | # Parent class for Elasticsearch-based providers that need to access 6 | # specific configuration directories. 7 | class Puppet::Provider::ElasticParsedFile < Puppet::Provider::ParsedFile 8 | # Find/set an x-pack configuration file. 9 | # 10 | # @return String 11 | def self.xpack_config(val) 12 | self.default_target ||= "/etc/elasticsearch/#{val}" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/puppet/provider/elastic_user_roles.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_yaml' 4 | 5 | # Provider to help manage file-based X-Pack user/role configuration 6 | # files. 7 | class Puppet::Provider::ElasticUserRoles < Puppet::Provider::ElasticYaml 8 | # Override the ancestor `parse` method to process a users/roles file 9 | # managed by the Elasticsearch user tools. 10 | def self.parse(text) 11 | lines = text.split("\n").map(&:strip).select do |line| 12 | # Strip comments 13 | (!line.start_with? '#') && !line.empty? 14 | end 15 | lines = lines.map do |line| 16 | # Turn array of roles into array of users that have the role 17 | role, users = line.split(':') 18 | users.split(',').map do |user| 19 | { user => [role] } 20 | end 21 | end 22 | lines = lines.flatten.reduce({}) do |hash, user| 23 | # Gather up user => role hashes by append-merging role lists 24 | hash.merge(user) { |_, o, n| o + n } 25 | end 26 | lines = lines.map do |user, roles| 27 | # Map those hashes into what the provider expects 28 | { 29 | name: user, 30 | roles: roles 31 | } 32 | end 33 | lines.to_a 34 | end 35 | 36 | # Represent this user/role record as a correctly-formatted config file. 37 | def self.to_file(records) 38 | debug "Flushing: #{records.inspect}" 39 | records = records.map do |record| 40 | record[:roles].map do |r| 41 | { [record[:name]] => r } 42 | end 43 | end 44 | records = records.flatten.map(&:invert).reduce({}) do |acc, role| 45 | acc.merge(role) { |_, o, n| o + n } 46 | end 47 | records = records.delete_if do |_, users| 48 | users.empty? 49 | end 50 | records = records.map do |role, users| 51 | "#{role}:#{users.join(',')}" 52 | end 53 | "#{records.join("\n")}\n" 54 | end 55 | 56 | def self.skip_record?(_record) 57 | false 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/puppet/provider/elastic_yaml.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet/provider/elastic_parsedfile' 6 | require 'puppet/util/package' 7 | require 'puppet_x/elastic/hash' 8 | 9 | # Provider for yaml-based Elasticsearch configuration files. 10 | class Puppet::Provider::ElasticYaml < Puppet::Provider::ElasticParsedFile 11 | class << self 12 | attr_accessor :metadata 13 | end 14 | 15 | # Transform a given string into a Hash-based representation of the 16 | # provider. 17 | def self.parse(text) 18 | yaml = YAML.safe_load text 19 | if yaml 20 | yaml.map do |key, metadata| 21 | { 22 | :name => key, 23 | :ensure => :present, 24 | @metadata => metadata 25 | } 26 | end 27 | else 28 | [] 29 | end 30 | end 31 | 32 | # Transform a given list of provider records into yaml-based 33 | # representation. 34 | def self.to_file(records) 35 | yaml = records.map do |record| 36 | # Convert top-level symbols to strings 37 | record.transform_keys(&:to_s) 38 | end 39 | yaml = yaml.reduce({}) do |hash, record| 40 | # Flatten array of hashes into single hash 41 | hash.merge(record['name'] => record.delete(@metadata.to_s)) 42 | end 43 | yaml = yaml.extend(Puppet_X::Elastic::SortedHash).to_yaml.split("\n") 44 | 45 | yaml.shift if yaml.first =~ %r{---} 46 | yaml = yaml.join("\n") 47 | 48 | yaml << "\n" 49 | end 50 | 51 | def self.skip_record?(_record) 52 | false 53 | end 54 | 55 | # This is ugly, but it's overridden in ParsedFile with abstract 56 | # functionality we don't need for our simple provider class. 57 | # This has been observed to break in Puppet version 3/4 switches. 58 | def self.valid_attr?(klass, attr_name) 59 | klass.is_a? Class ? klass.parameters.include?(attr_name) : true 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_component_template/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | require 'puppet_x/elastic/deep_to_i' 8 | require 'puppet_x/elastic/deep_to_s' 9 | 10 | Puppet::Type.type(:elasticsearch_component_template).provide( 11 | :ruby, 12 | parent: Puppet::Provider::ElasticREST, 13 | api_uri: '_component_template', 14 | metadata: :content, 15 | metadata_pipeline: [ 16 | lambda { |data| 17 | # As api returns values keyed under component_template 18 | data.merge!(data['component_template']) if data['component_template'].is_a? Hash 19 | data.delete('component_template') 20 | }, 21 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 22 | ->(data) { Puppet_X::Elastic.deep_to_i data } 23 | ] 24 | ) do 25 | desc 'A REST API based provider to manage Elasticsearch component templates.' 26 | 27 | mk_resource_methods 28 | 29 | # We need to override parent since actual data comes as array under component_templates key 30 | def self.process_body(body) 31 | JSON.parse(body).fetch('component_templates', []).map do |item| 32 | { 33 | :name => item['name'], 34 | :ensure => :present, 35 | metadata => process_metadata(item.keep_if { |key| key != 'name' }), 36 | :provider => name 37 | } 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_ilm_policy/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | require 'puppet_x/elastic/deep_to_i' 8 | require 'puppet_x/elastic/deep_to_s' 9 | 10 | Puppet::Type.type(:elasticsearch_ilm_policy).provide( 11 | :ruby, 12 | parent: Puppet::Provider::ElasticREST, 13 | api_uri: '_ilm/policy', 14 | metadata: :content, 15 | metadata_pipeline: [ 16 | # Since API returns unactionable keys like version, modified_date & in_use_by 17 | ->(data) { data.delete_if { |key, _value| !key.to_s.match(%r{policy}) } }, 18 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 19 | ->(data) { Puppet_X::Elastic.deep_to_i data } 20 | ] 21 | ) do 22 | desc 'A REST API based provider to manage Elasticsearch ILM policies.' 23 | 24 | mk_resource_methods 25 | end 26 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_index/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | require 'puppet_x/elastic/deep_to_i' 8 | require 'puppet_x/elastic/deep_to_s' 9 | 10 | Puppet::Type.type(:elasticsearch_index).provide( 11 | :ruby, 12 | parent: Puppet::Provider::ElasticREST, 13 | metadata: :settings, 14 | metadata_pipeline: [ 15 | ->(data) { data['settings'] }, 16 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 17 | ->(data) { Puppet_X::Elastic.deep_to_i data } 18 | ], 19 | api_uri: '_settings', 20 | api_discovery_uri: '_all', 21 | api_resource_style: :prefix, 22 | discrete_resource_creation: true 23 | ) do 24 | desc 'A REST API based provider to manage Elasticsearch index settings.' 25 | 26 | mk_resource_methods 27 | end 28 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_index_template/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | require 'puppet_x/elastic/deep_to_i' 8 | require 'puppet_x/elastic/deep_to_s' 9 | 10 | Puppet::Type.type(:elasticsearch_index_template).provide( 11 | :ruby, 12 | parent: Puppet::Provider::ElasticREST, 13 | api_uri: '_index_template', 14 | metadata: :content, 15 | metadata_pipeline: [ 16 | lambda { |data| 17 | # As api returns values keyed under index_template 18 | data.merge!(data['index_template']) if data['index_template'].is_a? Hash 19 | data.delete('index_template') 20 | }, 21 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 22 | ->(data) { Puppet_X::Elastic.deep_to_i data } 23 | ] 24 | ) do 25 | desc 'A REST API based provider to manage Elasticsearch index templates.' 26 | 27 | mk_resource_methods 28 | 29 | # We need to override parent since actual data comes as array under index_templates key 30 | def self.process_body(body) 31 | JSON.parse(body).fetch('index_templates', []).map do |item| 32 | { 33 | :name => item['name'], 34 | :ensure => :present, 35 | metadata => process_metadata(item.keep_if { |key| key != 'name' }), 36 | :provider => name 37 | } 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_license/xpack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_rest' 4 | 5 | Puppet::Type.type(:elasticsearch_license).provide( 6 | :xpack, 7 | api_resource_style: :bare, 8 | parent: Puppet::Provider::ElasticREST, 9 | metadata: :content, 10 | metadata_pipeline: [ 11 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 12 | ->(data) { Puppet_X::Elastic.deep_to_i data } 13 | ], 14 | api_uri: '_xpack/license', 15 | query_string: { 16 | 'acknowledge' => 'true' 17 | } 18 | ) do 19 | desc 'A REST API based provider to manage Elasticsearch X-Pack licenses.' 20 | 21 | mk_resource_methods 22 | 23 | def self.process_body(body) 24 | JSON.parse(body).map do |_object_name, api_object| 25 | { 26 | :name => name.to_s, 27 | :ensure => :present, 28 | metadata => { 'license' => process_metadata(api_object) }, 29 | :provider => name 30 | } 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_pipeline/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_rest' 4 | 5 | Puppet::Type.type(:elasticsearch_pipeline).provide( 6 | :ruby, 7 | parent: Puppet::Provider::ElasticREST, 8 | metadata: :content, 9 | api_uri: '_ingest/pipeline' 10 | ) do 11 | desc 'A REST API based provider to manage Elasticsearch ingest pipelines.' 12 | 13 | mk_resource_methods 14 | end 15 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_plugin/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_plugin' 4 | 5 | Puppet::Type.type(:elasticsearch_plugin).provide( 6 | :elasticsearch_plugin, 7 | parent: Puppet::Provider::ElasticPlugin 8 | ) do 9 | desc <<-END 10 | Post-5.x provider for Elasticsearch bin/elasticsearch-plugin 11 | command operations.' 12 | END 13 | 14 | case Facter.value('osfamily') 15 | when 'OpenBSD' 16 | commands plugin: '/usr/local/elasticsearch/bin/elasticsearch-plugin' 17 | commands es: '/usr/local/elasticsearch/bin/elasticsearch' 18 | commands javapathhelper: '/usr/local/bin/javaPathHelper' 19 | else 20 | if File.exist? '/usr/share/elasticsearch/bin/elasticsearch-plugin' 21 | commands plugin: '/usr/share/elasticsearch/bin/elasticsearch-plugin' 22 | else 23 | commands plugin: '/usr/share/elasticsearch/bin/plugin' 24 | end 25 | commands es: '/usr/share/elasticsearch/bin/elasticsearch' 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_role/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_yaml' 4 | 5 | Puppet::Type.type(:elasticsearch_role).provide( 6 | :ruby, 7 | parent: Puppet::Provider::ElasticYaml, 8 | metadata: :privileges 9 | ) do 10 | desc 'Provider for X-Pack role resources.' 11 | 12 | xpack_config 'roles.yml' 13 | end 14 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_role_mapping/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_yaml' 4 | 5 | Puppet::Type.type(:elasticsearch_role_mapping).provide( 6 | :ruby, 7 | parent: Puppet::Provider::ElasticYaml, 8 | metadata: :mappings 9 | ) do 10 | desc 'Provider for X-Pack role mappings.' 11 | 12 | xpack_config 'role_mapping.yml' 13 | end 14 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_slm_policy/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | require 'puppet_x/elastic/deep_to_i' 8 | require 'puppet_x/elastic/deep_to_s' 9 | 10 | Puppet::Type.type(:elasticsearch_slm_policy).provide( 11 | :ruby, 12 | parent: Puppet::Provider::ElasticREST, 13 | api_uri: '_slm/policy', 14 | metadata: :content, 15 | metadata_pipeline: [ 16 | # Since API returns actual policy keyed under policy. 17 | ->(data) { data['policy'] }, 18 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 19 | ->(data) { Puppet_X::Elastic.deep_to_i data } 20 | ] 21 | ) do 22 | desc 'A REST API based provider to manage Elasticsearch ILM policies.' 23 | 24 | mk_resource_methods 25 | end 26 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_snapshot_repository/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | Puppet::Type.type(:elasticsearch_snapshot_repository).provide( 8 | :ruby, 9 | parent: Puppet::Provider::ElasticREST, 10 | api_uri: '_snapshot' 11 | ) do 12 | desc 'A REST API based provider to manage Elasticsearch snapshot repositories.' 13 | 14 | mk_resource_methods 15 | 16 | def self.process_body(body) 17 | Puppet.debug('Got to snapshot_repository.process_body') 18 | 19 | JSON.parse(body).map do |object_name, api_object| 20 | { 21 | name: object_name, 22 | ensure: :present, 23 | type: api_object['type'], 24 | compress: api_object['settings']['compress'], 25 | location: api_object['settings']['location'], 26 | chunk_size: api_object['settings']['chunk_size'], 27 | max_restore_rate: api_object['settings']['max_restore_rate'], 28 | max_snapshot_rate: api_object['settings']['max_snapshot_rate'], 29 | provider: name 30 | }.compact 31 | end 32 | end 33 | 34 | def generate_body 35 | Puppet.debug('Got to snapshot_repository.generate_body') 36 | # Build core request body 37 | body = { 38 | 'type' => resource[:type], 39 | 'settings' => { 40 | 'compress' => resource[:compress], 41 | 'location' => resource[:location] 42 | } 43 | } 44 | 45 | # Add optional values 46 | body['settings']['chunk_size'] = resource[:chunk_size] unless resource[:chunk_size].nil? 47 | body['settings']['max_restore_rate'] = resource[:max_restore_rate] unless resource[:max_restore_rate].nil? 48 | body['settings']['max_snapshot_rate'] = resource[:max_snapshot_rate] unless resource[:max_snapshot_rate].nil? 49 | 50 | # Convert to JSON and return 51 | JSON.generate(body) 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_template/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | 5 | require 'puppet/provider/elastic_rest' 6 | 7 | require 'puppet_x/elastic/deep_to_i' 8 | require 'puppet_x/elastic/deep_to_s' 9 | 10 | Puppet::Type.type(:elasticsearch_template).provide( 11 | :ruby, 12 | parent: Puppet::Provider::ElasticREST, 13 | api_uri: '_template', 14 | metadata: :content, 15 | metadata_pipeline: [ 16 | ->(data) { Puppet_X::Elastic.deep_to_s data }, 17 | ->(data) { Puppet_X::Elastic.deep_to_i data } 18 | ] 19 | ) do 20 | desc 'A REST API based provider to manage Elasticsearch templates.' 21 | 22 | mk_resource_methods 23 | end 24 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_user/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet/provider/elastic_user_command') 4 | 5 | Puppet::Type.type(:elasticsearch_user).provide( 6 | :ruby, 7 | parent: Puppet::Provider::ElasticUserCommand 8 | ) do 9 | desc 'Provider for X-Pack user resources.' 10 | 11 | has_feature :manages_plaintext_passwords 12 | 13 | mk_resource_methods 14 | 15 | commands users_cli: "#{homedir}/bin/elasticsearch-users" 16 | commands es: "#{homedir}/bin/elasticsearch" 17 | end 18 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_user_file/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_parsedfile' 4 | 5 | Puppet::Type.type(:elasticsearch_user_file).provide( 6 | :ruby, 7 | parent: Puppet::Provider::ElasticParsedFile 8 | ) do 9 | desc 'Provider for X-Pack elasticsearch users using plain files.' 10 | 11 | xpack_config 'users' 12 | 13 | has_feature :manages_encrypted_passwords 14 | 15 | text_line :comment, 16 | match: %r{^\s*#} 17 | 18 | record_line :ruby, 19 | fields: %w[name hashed_password], 20 | separator: ':', 21 | joiner: ':' 22 | 23 | def self.valid_attr?(klass, attr_name) 24 | if klass.respond_to? :parameters 25 | klass.parameters.include?(attr_name) 26 | else 27 | true 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/puppet/provider/elasticsearch_user_roles/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/elastic_user_roles' 4 | 5 | Puppet::Type.type(:elasticsearch_user_roles).provide( 6 | :ruby, 7 | parent: Puppet::Provider::ElasticUserRoles 8 | ) do 9 | desc 'Provider for X-Pack user roles (parsed file.)' 10 | 11 | xpack_config 'users_roles' 12 | end 13 | -------------------------------------------------------------------------------- /lib/puppet/provider/es_instance_conn_validator/tcp_port.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) 4 | require 'puppet/util/es_instance_validator' 5 | 6 | # This file contains a provider for the resource type `es_instance_conn_validator`, 7 | # which validates the Elasticsearch connection by attempting a tcp connection. 8 | 9 | Puppet::Type.type(:es_instance_conn_validator).provide(:tcp_port) do 10 | desc "A provider for the resource type `es_instance_conn_validator`, 11 | which validates the connection by attempting an https 12 | connection to Elasticsearch." 13 | 14 | def exists? 15 | start_time = Time.now 16 | timeout = resource[:timeout] 17 | sleep_interval = resource[:sleep_interval] 18 | 19 | success = validator.attempt_connection 20 | 21 | while success == false && ((Time.now - start_time) < timeout) 22 | # It can take several seconds for the Elasticsearch to start up; 23 | # especially on the first install. Therefore, our first connection attempt 24 | # may fail. Here we have somewhat arbitrarily chosen to retry every 10 25 | # seconds until the configurable timeout has expired. 26 | Puppet.debug("Failed to connect to Elasticsearch; sleeping #{sleep_interval} seconds before retry") 27 | sleep sleep_interval 28 | success = validator.attempt_connection 29 | end 30 | 31 | if success 32 | Puppet.debug("Connected to the Elasticsearch in #{Time.now - start_time} seconds.") 33 | else 34 | Puppet.notice("Failed to connect to the Elasticsearch within timeout window of #{timeout} seconds; giving up.") 35 | end 36 | 37 | success 38 | end 39 | 40 | def create 41 | # If `#create` is called, that means that `#exists?` returned false, which 42 | # means that the connection could not be established... so we need to 43 | # cause a failure here. 44 | raise Puppet::Error, "Unable to connect to Elasticsearch! (#{@validator.instance_server}:#{@validator.instance_port})" 45 | end 46 | 47 | private 48 | 49 | # @api private 50 | def validator 51 | @validator ||= Puppet::Util::EsInstanceValidator.new(resource[:server], resource[:port]) 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_ilm_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet/file_serving/content' 6 | require 'puppet/file_serving/metadata' 7 | 8 | require 'puppet_x/elastic/deep_implode' 9 | require 'puppet_x/elastic/deep_to_i' 10 | require 'puppet_x/elastic/deep_to_s' 11 | require 'puppet_x/elastic/elasticsearch_rest_resource' 12 | 13 | Puppet::Type.newtype(:elasticsearch_ilm_policy) do 14 | extend ElasticsearchRESTResource 15 | 16 | desc 'Manages Elasticsearch ILM policies.' 17 | 18 | ensurable 19 | 20 | newparam(:name, namevar: true) do 21 | desc 'Policy name.' 22 | end 23 | 24 | newproperty(:content) do 25 | desc 'Structured content of policy.' 26 | 27 | validate do |value| 28 | raise Puppet::Error, 'hash expected' unless value.is_a? Hash 29 | end 30 | 31 | def insync?(value) 32 | Puppet_X::Elastic.deep_implode(value) == 33 | Puppet_X::Elastic.deep_implode(should) 34 | end 35 | 36 | munge do |value| 37 | Puppet_X::Elastic.deep_to_i(Puppet_X::Elastic.deep_to_s(value)) 38 | end 39 | end 40 | 41 | newparam(:source) do 42 | desc 'Puppet source to file containing ILM policy contents.' 43 | 44 | validate do |value| 45 | raise Puppet::Error, 'string expected' unless value.is_a? String 46 | end 47 | end 48 | 49 | # rubocop:disable Style/SignalException 50 | validate do 51 | # Ensure that at least one source of ILM policy content has been provided 52 | if self[:ensure] == :present 53 | fail Puppet::ParseError, '"content" or "source" required' \ 54 | if self[:content].nil? && self[:source].nil? 55 | 56 | if !self[:content].nil? && !self[:source].nil? 57 | fail( 58 | Puppet::ParseError, 59 | "'content' and 'source' cannot be simultaneously defined" 60 | ) 61 | end 62 | end 63 | 64 | # If a source was passed, retrieve the source content from Puppet's 65 | # FileServing indirection and set the content property 66 | unless self[:source].nil? 67 | fail(format('Could not retrieve source %s', self[:source])) unless Puppet::FileServing::Metadata.indirection.find(self[:source]) 68 | 69 | tmp = if !catalog.nil? \ 70 | && catalog.respond_to?(:environment_instance) 71 | Puppet::FileServing::Content.indirection.find( 72 | self[:source], 73 | environment: catalog.environment_instance 74 | ) 75 | else 76 | Puppet::FileServing::Content.indirection.find(self[:source]) 77 | end 78 | 79 | fail(format('Could not find any content at %s', self[:source])) unless tmp 80 | 81 | self[:content] = JSON.parse(tmp.content) 82 | end 83 | end 84 | # rubocop:enable Style/SignalException 85 | end 86 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_index.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet_x/elastic/asymmetric_compare' 6 | require 'puppet_x/elastic/deep_to_i' 7 | require 'puppet_x/elastic/deep_to_s' 8 | require 'puppet_x/elastic/elasticsearch_rest_resource' 9 | 10 | Puppet::Type.newtype(:elasticsearch_index) do 11 | extend ElasticsearchRESTResource 12 | 13 | desc 'Manages Elasticsearch index settings.' 14 | 15 | ensurable 16 | 17 | newparam(:name, namevar: true) do 18 | desc 'Index name.' 19 | end 20 | 21 | newproperty(:settings) do 22 | desc 'Structured settings for the index in hash form.' 23 | 24 | def insync?(value) 25 | Puppet_X::Elastic.asymmetric_compare(should, value) 26 | end 27 | 28 | munge do |value| 29 | Puppet_X::Elastic.deep_to_i(Puppet_X::Elastic.deep_to_s(value)) 30 | end 31 | 32 | validate do |value| 33 | raise Puppet::Error, 'hash expected' unless value.is_a? Hash 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_keystore.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/parameter/boolean' 4 | 5 | Puppet::Type.newtype(:elasticsearch_keystore) do 6 | desc 'Manages an Elasticsearch keystore settings file.' 7 | 8 | ensurable 9 | 10 | newparam(:instance, namevar: true) do 11 | desc 'Elasticsearch instance this keystore belongs to.' 12 | end 13 | 14 | newparam(:configdir) do 15 | desc 'Path to the elasticsearch configuration directory (ES_PATH_CONF).' 16 | defaultto '/etc/elasticsearch' 17 | end 18 | 19 | newparam(:purge, boolean: true, parent: Puppet::Parameter::Boolean) do 20 | desc <<-EOS 21 | Whether to proactively remove settings that exist in the keystore but 22 | are not present in this resource's settings. 23 | EOS 24 | 25 | defaultto false 26 | end 27 | 28 | newproperty(:settings, array_matching: :all) do 29 | desc 'A key/value hash of settings names and values.' 30 | 31 | # The keystore utility can only retrieve a list of stored settings, 32 | # so here we only compare the existing settings (sorted) with the 33 | # desired settings' keys 34 | def insync?(value) 35 | if resource[:purge] 36 | value.sort == @should.first.keys.sort 37 | else 38 | (@should.first.keys - value).empty? 39 | end 40 | end 41 | 42 | def change_to_s(currentvalue, newvalue_raw) 43 | ret = '' 44 | 45 | newvalue = newvalue_raw.first.keys 46 | 47 | added_settings = newvalue - currentvalue 48 | ret << "added: #{added_settings.join(', ')} " unless added_settings.empty? 49 | 50 | removed_settings = currentvalue - newvalue 51 | unless removed_settings.empty? 52 | ret << if resource[:purge] 53 | "removed: #{removed_settings.join(', ')}" 54 | else 55 | "would have removed: #{removed_settings.join(', ')}, but purging is disabled" 56 | end 57 | end 58 | 59 | ret 60 | end 61 | end 62 | 63 | autorequire(:augeas) do 64 | "defaults_#{self[:name]}" 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_license.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet_x/elastic/asymmetric_compare' 6 | require 'puppet_x/elastic/deep_to_i' 7 | require 'puppet_x/elastic/deep_to_s' 8 | require 'puppet_x/elastic/elasticsearch_rest_resource' 9 | 10 | Puppet::Type.newtype(:elasticsearch_license) do 11 | extend ElasticsearchRESTResource 12 | 13 | desc 'Manages Elasticsearch licenses.' 14 | 15 | ensurable 16 | 17 | newparam(:name, namevar: true) do 18 | desc 'Pipeline name.' 19 | end 20 | 21 | newproperty(:content) do 22 | desc 'Structured hash for license content data.' 23 | 24 | def insync?(value) 25 | Puppet_X::Elastic.asymmetric_compare( 26 | should.transform_values { |v| v.is_a?(Hash) ? (v.reject { |s, _| s == 'signature' }) : v }, 27 | value 28 | ) 29 | end 30 | 31 | def should_to_s(newvalue) 32 | newvalue.transform_values do |license_data| 33 | if license_data.is_a? Hash 34 | license_data.to_h do |field, value| 35 | [field, field == 'signature' ? '[redacted]' : value] 36 | end 37 | else 38 | v 39 | end 40 | end.to_s 41 | end 42 | 43 | validate do |value| 44 | raise Puppet::Error, 'hash expected' unless value.is_a? Hash 45 | end 46 | 47 | munge do |value| 48 | Puppet_X::Elastic.deep_to_i(Puppet_X::Elastic.deep_to_s(value)) 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_pipeline.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet_x/elastic/deep_to_i' 6 | require 'puppet_x/elastic/deep_to_s' 7 | require 'puppet_x/elastic/elasticsearch_rest_resource' 8 | 9 | Puppet::Type.newtype(:elasticsearch_pipeline) do 10 | extend ElasticsearchRESTResource 11 | 12 | desc 'Manages Elasticsearch ingest pipelines.' 13 | 14 | ensurable 15 | 16 | newparam(:name, namevar: true) do 17 | desc 'Pipeline name.' 18 | end 19 | 20 | newproperty(:content) do 21 | desc 'Structured content of pipeline.' 22 | 23 | validate do |value| 24 | raise Puppet::Error, 'hash expected' unless value.is_a? Hash 25 | end 26 | 27 | munge do |value| 28 | Puppet_X::Elastic.deep_to_i(Puppet_X::Elastic.deep_to_s(value)) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_plugin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:elasticsearch_plugin) do 4 | @doc = 'Plugin installation type' 5 | 6 | ensurable 7 | 8 | newparam(:name, namevar: true) do 9 | desc 'An arbitrary name used as the identity of the resource.' 10 | end 11 | 12 | newparam(:configdir) do 13 | desc 'Path to the elasticsearch configuration directory (ES_PATH_CONF).' 14 | defaultto '/etc/elasticsearch' 15 | 16 | validate do |value| 17 | raise Puppet::Error, 'path expected' if value.nil? 18 | end 19 | end 20 | 21 | newparam(:elasticsearch_package_name) do 22 | desc 'Name of the system Elasticsearch package.' 23 | end 24 | 25 | newparam(:java_opts) do 26 | desc 'Optional array of Java options for ES_JAVA_OPTS.' 27 | defaultto [] 28 | end 29 | 30 | newparam(:java_home) do 31 | desc 'Optional string to set the environment variable JAVA_HOME.' 32 | end 33 | 34 | newparam(:url) do 35 | desc 'Url of the package' 36 | end 37 | 38 | newparam(:source) do 39 | desc 'Source of the package. puppet:// or file:// resource' 40 | end 41 | 42 | newparam(:proxy) do 43 | desc 'Proxy Host' 44 | end 45 | 46 | newparam(:plugin_dir) do 47 | desc 'Path to the Plugins directory' 48 | defaultto '/usr/share/elasticsearch/plugins' 49 | end 50 | 51 | newparam(:plugin_path) do 52 | desc 'Override name of the directory created for the plugin' 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_role.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:elasticsearch_role) do 4 | desc 'Type to model Elasticsearch roles.' 5 | 6 | ensurable 7 | 8 | newparam(:name, namevar: true) do 9 | desc 'Role name.' 10 | 11 | newvalues(%r{^[a-zA-Z_]{1}[-\w@.$]{0,39}$}) 12 | end 13 | 14 | newproperty(:privileges) do 15 | desc 'Security privileges of the given role.' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_role_mapping.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:elasticsearch_role_mapping) do 4 | desc 'Type to model Elasticsearch role mappings.' 5 | 6 | ensurable 7 | 8 | newparam(:name, namevar: true) do 9 | desc 'Role name.' 10 | 11 | newvalues(%r{^[a-zA-Z_]{1}[-\w@.$]{0,39}$}) 12 | end 13 | 14 | newproperty(:mappings, array_matching: :all) do 15 | desc 'List of role mappings.' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_slm_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet/file_serving/content' 6 | require 'puppet/file_serving/metadata' 7 | 8 | require 'puppet_x/elastic/deep_implode' 9 | require 'puppet_x/elastic/deep_to_i' 10 | require 'puppet_x/elastic/deep_to_s' 11 | require 'puppet_x/elastic/elasticsearch_rest_resource' 12 | 13 | Puppet::Type.newtype(:elasticsearch_slm_policy) do 14 | extend ElasticsearchRESTResource 15 | 16 | desc 'Manages Elasticsearch SLM policies.' 17 | 18 | ensurable 19 | 20 | newparam(:name, namevar: true) do 21 | desc 'Policy name.' 22 | end 23 | 24 | newproperty(:content) do 25 | desc 'Structured content of policy.' 26 | 27 | validate do |value| 28 | raise Puppet::Error, 'hash expected' unless value.is_a? Hash 29 | end 30 | 31 | def insync?(value) 32 | Puppet_X::Elastic.deep_implode(value) == 33 | Puppet_X::Elastic.deep_implode(should) 34 | end 35 | 36 | munge do |value| 37 | Puppet_X::Elastic.deep_to_i(Puppet_X::Elastic.deep_to_s(value)) 38 | end 39 | end 40 | 41 | newparam(:source) do 42 | desc 'Puppet source to file containing SLM policy contents.' 43 | 44 | validate do |value| 45 | raise Puppet::Error, 'string expected' unless value.is_a? String 46 | end 47 | end 48 | 49 | # rubocop:disable Style/SignalException 50 | validate do 51 | # Ensure that at least one source of ILM policy content has been provided 52 | if self[:ensure] == :present 53 | fail Puppet::ParseError, '"content" or "source" required' \ 54 | if self[:content].nil? && self[:source].nil? 55 | 56 | if !self[:content].nil? && !self[:source].nil? 57 | fail( 58 | Puppet::ParseError, 59 | "'content' and 'source' cannot be simultaneously defined" 60 | ) 61 | end 62 | end 63 | 64 | # If a source was passed, retrieve the source content from Puppet's 65 | # FileServing indirection and set the content property 66 | unless self[:source].nil? 67 | fail(format('Could not retrieve source %s', self[:source])) unless Puppet::FileServing::Metadata.indirection.find(self[:source]) 68 | 69 | tmp = if !catalog.nil? \ 70 | && catalog.respond_to?(:environment_instance) 71 | Puppet::FileServing::Content.indirection.find( 72 | self[:source], 73 | environment: catalog.environment_instance 74 | ) 75 | else 76 | Puppet::FileServing::Content.indirection.find(self[:source]) 77 | end 78 | 79 | fail(format('Could not find any content at %s', self[:source])) unless tmp 80 | 81 | self[:content] = JSON.parse(tmp.content) 82 | end 83 | end 84 | # rubocop:enable Style/SignalException 85 | end 86 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_snapshot_repository.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | 5 | require 'puppet_x/elastic/elasticsearch_rest_resource' 6 | 7 | Puppet::Type.newtype(:elasticsearch_snapshot_repository) do 8 | extend ElasticsearchRESTResource 9 | 10 | desc 'Manages Elasticsearch snapshot repositories.' 11 | 12 | ensurable 13 | 14 | newparam(:name, namevar: true) do 15 | desc 'Repository name.' 16 | end 17 | 18 | newparam(:type) do 19 | desc 'Repository type' 20 | defaultto 'fs' 21 | 22 | validate do |value| 23 | raise Puppet::Error, 'string expected' unless value.is_a? String 24 | end 25 | end 26 | 27 | # newproperty(:compress, :boolean => true, :parent => Puppet::Property::Boolean) do 28 | newproperty(:compress, boolean: true) do 29 | desc 'Compress the repository data' 30 | 31 | defaultto true 32 | end 33 | 34 | newproperty(:location) do 35 | desc 'Repository location' 36 | end 37 | 38 | newproperty(:chunk_size) do 39 | desc 'File chunk size' 40 | end 41 | 42 | newproperty(:max_restore_rate) do 43 | desc 'Maximum Restore rate' 44 | end 45 | 46 | newproperty(:max_snapshot_rate) do 47 | desc 'Maximum Snapshot rate' 48 | end 49 | 50 | validate do 51 | raise ArgumentError, 'Location is required.' if self[:location].nil? 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:elasticsearch_user) do 4 | desc 'Type to model Elasticsearch users.' 5 | 6 | feature :manages_plaintext_passwords, 7 | 'The provider can control the password in plaintext form.' 8 | 9 | ensurable 10 | 11 | newparam(:name, namevar: true) do 12 | desc 'User name.' 13 | end 14 | 15 | newparam(:configdir) do 16 | desc 'Path to the elasticsearch configuration directory (ES_PATH_CONF).' 17 | 18 | validate do |value| 19 | raise Puppet::Error, 'path expected' if value.nil? 20 | end 21 | end 22 | 23 | newparam( 24 | :password, 25 | required_features: :manages_plaintext_passwords 26 | ) do 27 | desc 'Plaintext password for user.' 28 | 29 | validate do |value| 30 | raise ArgumentError, 'Password must be at least 6 characters long' if value.length < 6 31 | end 32 | 33 | def is_to_s(_currentvalue) 34 | '[old password hash redacted]' 35 | end 36 | 37 | def should_to_s(_newvalue) 38 | '[new password hash redacted]' 39 | end 40 | end 41 | 42 | def refresh 43 | if @parameters[:ensure] 44 | provider.passwd 45 | else 46 | debug 'skipping password set' 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_user_file.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:elasticsearch_user_file) do 4 | desc 'Type to model Elasticsearch users.' 5 | 6 | feature :manages_encrypted_passwords, 7 | 'The provider can control the password hash without a need 8 | to explicitly refresh.' 9 | 10 | ensurable 11 | 12 | newparam(:name, namevar: true) do 13 | desc 'User name.' 14 | end 15 | 16 | newparam(:configdir) do 17 | desc 'Path to the elasticsearch configuration directory (ES_PATH_CONF).' 18 | 19 | validate do |value| 20 | raise Puppet::Error, 'path expected' if value.nil? 21 | end 22 | end 23 | 24 | newproperty( 25 | :hashed_password, 26 | required_features: :manages_encrypted_passwords 27 | ) do 28 | desc 'Hashed password for user.' 29 | 30 | newvalues(%r{^[$]2a[$].{56}$}) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/puppet/type/elasticsearch_user_roles.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:elasticsearch_user_roles) do 4 | desc 'Type to model Elasticsearch user roles.' 5 | 6 | ensurable 7 | 8 | newparam(:name, namevar: true) do 9 | desc 'User name.' 10 | end 11 | 12 | newproperty(:roles, array_matching: :all) do 13 | desc 'Array of roles that the user should belong to.' 14 | def insync?(value) 15 | value.sort == should.sort 16 | end 17 | end 18 | 19 | autorequire(:elasticsearch_user) do 20 | self[:name] 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/puppet/type/es_instance_conn_validator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:es_instance_conn_validator) do 4 | @doc = "Verify that a connection can be successfully established between a 5 | node and Elasticsearch. It could potentially be used for other purposes 6 | such as monitoring." 7 | 8 | ensurable 9 | 10 | newparam(:name, namevar: true) do 11 | desc 'An arbitrary name used as the identity of the resource.' 12 | end 13 | 14 | newparam(:server) do 15 | desc 'DNS name or IP address of the server where Elasticsearch should be running.' 16 | defaultto 'localhost' 17 | end 18 | 19 | newparam(:port) do 20 | desc 'The port that the Elasticsearch instance should be listening on.' 21 | defaultto 9200 22 | end 23 | 24 | newparam(:timeout) do 25 | desc 'The max number of seconds that the validator should wait before giving up and deciding that Elasticsearch is not running; defaults to 60 seconds.' 26 | defaultto 60 27 | validate do |value| 28 | # This will raise an error if the string is not convertible to an integer 29 | Integer(value) 30 | end 31 | munge do |value| 32 | Integer(value) 33 | end 34 | end 35 | 36 | newparam(:sleep_interval) do 37 | desc 'The number of seconds that the validator should wait before retrying the connection to Elasticsearch; defaults to 10 seconds.' 38 | defaultto 10 39 | validate do |value| 40 | # This will raise an error if the string is not convertible to an integer 41 | Integer(value) 42 | end 43 | munge do |value| 44 | Integer(value) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/puppet/util/es_instance_validator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'socket' 4 | require 'timeout' 5 | 6 | module Puppet 7 | # Namespace for miscellaneous tools 8 | module Util 9 | # Helper class to assist with talking to the Elasticsearch service ports. 10 | class EsInstanceValidator 11 | attr_reader :instance_server, :instance_port 12 | 13 | def initialize(instance_server, instance_port) 14 | @instance_server = instance_server 15 | @instance_port = instance_port 16 | 17 | # Avoid deprecation warnings in Puppet versions < 4 18 | @timeout = if Facter.value(:puppetversion).split('.').first.to_i < 4 19 | Puppet[:configtimeout] 20 | else 21 | Puppet[:http_connect_timeout] 22 | end 23 | end 24 | 25 | # Utility method; attempts to make an https connection to the Elasticsearch instance. 26 | # This is abstracted out into a method so that it can be called multiple times 27 | # for retry attempts. 28 | # 29 | # @return true if the connection is successful, false otherwise. 30 | def attempt_connection 31 | Timeout.timeout(@timeout) do 32 | TCPSocket.new(@instance_server, @instance_port).close 33 | true 34 | rescue Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e 35 | Puppet.debug "Unable to connect to Elasticsearch instance (#{@instance_server}:#{@instance_port}): #{e.message}" 36 | false 37 | end 38 | rescue Timeout::Error 39 | false 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/asymmetric_compare.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 4 | # Custom Elastic functions 5 | module Elastic 6 | # Certain Elasticsearch APIs return fields that are present in responses 7 | # but not present when sending API requests such as creation time, and so 8 | # on. When comparing desired settings and extant settings, only indicate 9 | # that a value differs from another when user-desired settings differ from 10 | # existing settings - we ignore keys that exist in the response that aren't 11 | # being explicitly controlled by Puppet. 12 | def self.asymmetric_compare(should_val, is_val) 13 | should_val.reduce(true) do |is_synced, (should_key, should_setting)| 14 | if is_val.key? should_key 15 | if is_val[should_key].is_a? Hash 16 | asymmetric_compare(should_setting, is_val[should_key]) 17 | else 18 | is_synced && is_val[should_key] == should_setting 19 | end 20 | else 21 | is_synced && true 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/deep_implode.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 4 | # Custom ruby for some Elastic utilities. 5 | module Elastic 6 | # Recursively implode a hash into dot-delimited structure of Hash 7 | # keys/values. 8 | def self.deep_implode(hash) 9 | ret = {} 10 | implode ret, hash 11 | ret 12 | end 13 | 14 | # Recursively descend into hash values, flattening the key structure into 15 | # dot-delimited keyed Hash. 16 | def self.implode(new_hash, hash, path = []) 17 | hash.sort_by { |k, _v| k.length }.reverse.each do |key, value| 18 | new_path = path + [key] 19 | case value 20 | when Hash 21 | implode(new_hash, value, new_path) 22 | else 23 | new_key = new_path.join('.') 24 | if value.is_a?(Array) \ 25 | && new_hash.key?(new_key) \ 26 | && new_hash[new_key].is_a?(Array) 27 | new_hash[new_key] += value 28 | else 29 | new_hash[new_key] ||= value 30 | end 31 | end 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/deep_to_i.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 4 | # Custom Elastic functions 5 | module Elastic 6 | # This ugly hack is required due to the fact Puppet passes in the 7 | # puppet-native hash with stringified numerics, which causes the 8 | # decoded JSON from the Elasticsearch API to be seen as out-of-sync 9 | # when the parsed template hash is compared against the puppet hash. 10 | def self.deep_to_i(obj) 11 | if obj.is_a?(String) && obj =~ %r{^-?[0-9]+$} 12 | obj.to_i 13 | elsif obj.is_a? Array 14 | obj.map { |element| deep_to_i(element) } 15 | elsif obj.is_a? Hash 16 | obj.merge(obj) { |_key, val| deep_to_i(val) } 17 | else 18 | obj 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/deep_to_s.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 4 | # Custom Elastic functions 5 | module Elastic 6 | # When given a hash, this method recurses deeply into all values to convert 7 | # any that aren't data structures into strings. This is necessary when 8 | # comparing results from Elasticsearch API calls, because values like 9 | # integers and booleans are in string form. 10 | def self.deep_to_s(obj) 11 | if obj.is_a? Array 12 | obj.map { |element| deep_to_s(element) } 13 | elsif obj.is_a? Hash 14 | obj.merge(obj) { |_key, val| deep_to_s(val) } 15 | elsif (!obj.is_a? String) && ![true, false].include?(obj) && obj.respond_to?(:to_s) 16 | obj.to_s 17 | else 18 | obj 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/elasticsearch_rest_resource.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/parameter/boolean' 4 | 5 | # Provides common properties and parameters for REST-based Elasticsearch types 6 | module ElasticsearchRESTResource 7 | def self.extended(extender) 8 | extender.newparam(:ca_file) do 9 | desc 'Absolute path to a CA file to authenticate server certs against.' 10 | end 11 | 12 | extender.newparam(:ca_path) do 13 | desc 'Absolute path to a directory containing CA files.' 14 | end 15 | 16 | extender.newparam(:host) do 17 | desc 'Hostname or address of Elasticsearch instance.' 18 | defaultto 'localhost' 19 | 20 | validate do |value| 21 | raise Puppet::Error, 'invalid parameter, expected string' unless value.is_a? String 22 | end 23 | end 24 | 25 | extender.newparam(:password) do 26 | desc 'Optional HTTP basic auth plaintext password for Elasticsearch.' 27 | end 28 | 29 | extender.newparam(:port) do 30 | desc 'Port to use for Elasticsearch HTTP API operations.' 31 | defaultto 9200 32 | 33 | munge do |value| 34 | case value 35 | when String 36 | value.to_i 37 | when Integer 38 | value 39 | else 40 | raise Puppet::Error, "unknown '#{value}' timeout type #{value.class}" 41 | end 42 | end 43 | 44 | validate do |value| 45 | raise Puppet::Error, "invalid port value '#{value}'" \ 46 | unless value.to_s =~ %r{^([0-9]+)$} 47 | raise Puppet::Error, "invalid port value '#{value}'" \ 48 | unless Regexp.last_match[0].to_i.positive? \ 49 | && (Regexp.last_match[0].to_i < 65_535) 50 | end 51 | end 52 | 53 | extender.newparam(:protocol) do 54 | desc 'Protocol to use for communication with Elasticsearch.' 55 | defaultto 'http' 56 | end 57 | 58 | extender.newparam(:timeout) do 59 | desc 'HTTP timeout for reading/writing content to Elasticsearch.' 60 | defaultto 10 61 | 62 | munge do |value| 63 | case value 64 | when String 65 | value.to_i 66 | when Integer 67 | value 68 | else 69 | raise Puppet::Error, "unknown '#{value}' timeout type #{value.class}" 70 | end 71 | end 72 | 73 | validate do |value| 74 | raise Puppet::Error, 'timeout must be a positive integer' if value.to_s !~ %r{^\d+$} 75 | end 76 | end 77 | 78 | extender.newparam(:username) do 79 | desc 'Optional HTTP basic auth username for Elasticsearch.' 80 | end 81 | 82 | extender.newparam( 83 | :validate_tls, 84 | boolean: true, 85 | parent: Puppet::Parameter::Boolean 86 | ) do 87 | desc 'Whether to verify TLS/SSL certificates.' 88 | defaultto true 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/es_versioning.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ElasticsearchPackageNotFoundError < StandardError; end 4 | 5 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 6 | module Elastic 7 | # Assists with discerning the locally installed version of Elasticsearch. 8 | # Implemented in a way to be called from native types and providers in order 9 | # to lazily fetch the package version from various arcane Puppet mechanisms. 10 | class EsVersioning 11 | # All of the default options we'll set for Elasticsearch's command 12 | # invocation. 13 | DEFAULT_OPTS = { 14 | 'home' => 'ES_HOME', 15 | 'logs' => 'LOG_DIR', 16 | 'data' => 'DATA_DIR', 17 | 'work' => 'WORK_DIR', 18 | 'conf' => 'CONF_DIR' 19 | }.freeze 20 | 21 | # Create an array of command-line flags to append to an `elasticsearch` 22 | # startup command. 23 | def self.opt_flags(package_name, catalog, opts = DEFAULT_OPTS.dup) 24 | opt_flag = opt_flag(min_version('5.0.0', package_name, catalog)) 25 | 26 | opts.delete 'work' if min_version '5.0.0', package_name, catalog 27 | opts.delete 'home' if min_version '5.4.0', package_name, catalog 28 | 29 | opt_args = if min_version '6.0.0', package_name, catalog 30 | [] 31 | else 32 | opts.map do |k, v| 33 | "-#{opt_flag}default.path.#{k}=${#{v}}" 34 | end.sort 35 | end 36 | 37 | opt_args << '--quiet' if min_version '5.0.0', package_name, catalog 38 | 39 | [opt_flag, opt_args] 40 | end 41 | 42 | # Get the correct option flag depending on whether Elasticsearch is post 43 | # version 5. 44 | def self.opt_flag(v5_or_later) 45 | v5_or_later ? 'E' : 'Des.' 46 | end 47 | 48 | # Predicate to determine whether a package is at least a certain version. 49 | def self.min_version(ver, package_name, catalog) 50 | Puppet::Util::Package.versioncmp( 51 | version(package_name, catalog), ver 52 | ) >= 0 53 | end 54 | 55 | # Fetch the package version for a locally installed package. 56 | def self.version(package_name, catalog) 57 | es_pkg = catalog.resource("Package[#{package_name}]") 58 | raise Puppet::Error, "could not find `Package[#{package_name}]` resource" unless es_pkg 59 | 60 | [ 61 | es_pkg.provider.properties[:version], 62 | es_pkg.provider.properties[:ensure] 63 | ].each do |property| 64 | return property if property.is_a? String 65 | end 66 | Puppet.warning("could not find valid version for `Package[#{package_name}]` resource") 67 | raise ElasticsearchPackageNotFoundError 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/hash.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Custom extensions namespace 4 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 5 | # Elastic helpers 6 | module Elastic 7 | # Utility extension for consistent to_yaml behavior. 8 | module SortedHash 9 | # Upon extension, modify the hash appropriately to render 10 | # sorted yaml dependent upon whichever way is supported for 11 | # this version of Puppet/Ruby's yaml implementation. 12 | def self.extended(base) 13 | if RUBY_VERSION >= '1.9' 14 | # We can sort the hash in Ruby >= 1.9 by recursively 15 | # re-inserting key/values in sorted order. Native to_yaml will 16 | # call .each and get sorted pairs back. 17 | tmp = base.to_a.sort 18 | base.clear 19 | tmp.each do |key, val| 20 | case val 21 | when base.class 22 | val.extend Puppet_X::Elastic::SortedHash 23 | when Array 24 | val.map do |elem| 25 | if elem.is_a? base.class 26 | elem.extend(Puppet_X::Elastic::SortedHash) 27 | else 28 | elem 29 | end 30 | end 31 | end 32 | base[key] = val 33 | end 34 | else 35 | # Otherwise, recurse into the hash to extend all nested 36 | # hashes with the sorted each_pair method. 37 | # 38 | # Ruby < 1.9 doesn't support any notion of sorted hashes, 39 | # so we have to expressly monkey patch each_pair, which is 40 | # called by ZAML (the yaml library used in Puppet < 4; Puppet 41 | # >= 4 deprecates Ruby 1.8) 42 | # 43 | # Note that respond_to? is used here as there were weird 44 | # problems with .class/.is_a? 45 | base.merge! base do |_, ov, _| 46 | if ov.respond_to? :each_pair 47 | ov.extend Puppet_X::Elastic::SortedHash 48 | elsif ov.is_a? Array 49 | ov.map do |elem| 50 | if elem.respond_to? :each_pair 51 | elem.extend Puppet_X::Elastic::SortedHash 52 | else 53 | elem 54 | end 55 | end 56 | else 57 | ov 58 | end 59 | end 60 | end 61 | end 62 | 63 | # Override each_pair with a method that yields key/values in 64 | # sorted order. 65 | def each_pair 66 | return to_enum(:each_pair) unless block_given? 67 | 68 | keys.sort.each do |key| 69 | yield key, self[key] 70 | end 71 | self 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/puppet_x/elastic/plugin_parsing.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ElasticPluginParseFailure < StandardError; end 4 | 5 | module Puppet_X # rubocop:disable Style/ClassAndModuleCamelCase 6 | # Custom functions for plugin string parsing. 7 | module Elastic 8 | def self.plugin_name(raw_name) 9 | plugin_split(raw_name, 1) 10 | end 11 | 12 | def self.plugin_version(raw_name) 13 | v = plugin_split(raw_name, 2, false).gsub(%r{^[^0-9]*}, '') 14 | raise ElasticPluginParseFailure, "could not parse version, got '#{v}'" if v.empty? 15 | 16 | v 17 | end 18 | 19 | # Attempt to guess at the plugin's final directory name 20 | def self.plugin_split(original_string, position, soft_fail = true) 21 | # Try both colon (maven) and slash-delimited (github/elastic.co) names 22 | %w[/ :].each do |delimiter| 23 | parts = original_string.split(delimiter) 24 | # If the string successfully split, assume we found the right format 25 | return parts[position].gsub(%r{(elasticsearch-|es-)}, '') unless parts[position].nil? 26 | end 27 | 28 | unless soft_fail 29 | raise( 30 | ElasticPluginParseFailure, 31 | "could not find element '#{position}' in #{original_string}" 32 | ) 33 | end 34 | 35 | original_string 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /manifests/role.pp: -------------------------------------------------------------------------------- 1 | # Manage x-pack roles. 2 | # 3 | # @param ensure 4 | # Whether the role should be present or not. 5 | # Set to 'absent' to ensure a role is not present. 6 | # 7 | # @param mappings 8 | # A list of optional mappings defined for this role. 9 | # 10 | # @param privileges 11 | # A hash of permissions defined for the role. Valid privilege settings can 12 | # be found in the x-pack documentation. 13 | # 14 | # @example create and manage the role 'power_user' mapped to an LDAP group. 15 | # elasticsearch::role { 'power_user': 16 | # privileges => { 17 | # 'cluster' => 'monitor', 18 | # 'indices' => { 19 | # '*' => 'all', 20 | # }, 21 | # }, 22 | # mappings => [ 23 | # "cn=users,dc=example,dc=com", 24 | # ], 25 | # } 26 | # 27 | # @author Tyler Langlois 28 | # @author Gavin Williams 29 | # 30 | define elasticsearch::role ( 31 | Enum['absent', 'present'] $ensure = 'present', 32 | Array $mappings = [], 33 | Hash $privileges = {}, 34 | ) { 35 | #validate_slength($name, 40, 1) 36 | if ($name.length < 1 or $name.length > 40) { 37 | fail("Invalid length role name '${name}' must be between 1 and 40") 38 | } 39 | 40 | if empty($privileges) or $ensure == 'absent' { 41 | $_role_ensure = 'absent' 42 | } else { 43 | $_role_ensure = $ensure 44 | } 45 | 46 | if empty($mappings) or $ensure == 'absent' { 47 | $_mapping_ensure = 'absent' 48 | } else { 49 | $_mapping_ensure = $ensure 50 | } 51 | 52 | elasticsearch_role { $name : 53 | ensure => $_role_ensure, 54 | privileges => $privileges, 55 | } 56 | 57 | elasticsearch_role_mapping { $name : 58 | ensure => $_mapping_ensure, 59 | mappings => $mappings, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /manifests/script.pp: -------------------------------------------------------------------------------- 1 | # This define allows you to insert, update or delete scripts that are used 2 | # within Elasticsearch. 3 | # 4 | # @param ensure 5 | # Controls the state of the script file resource to manage. 6 | # Values are simply passed through to the `file` resource. 7 | # 8 | # @param recurse 9 | # Will be passed through to the script file resource. 10 | # 11 | # @param source 12 | # Puppet source of the script 13 | # 14 | # @author Richard Pijnenburg 15 | # @author Tyler Langlois 16 | # 17 | define elasticsearch::script ( 18 | String $source, 19 | String $ensure = 'present', 20 | Optional[Variant[Boolean, Enum['remote']]] $recurse = undef, 21 | ) { 22 | if ! defined(Class['elasticsearch']) { 23 | fail('You must include the elasticsearch base class before using defined resources') 24 | } 25 | 26 | $filename_array = split($source, '/') 27 | $basefilename = $filename_array[-1] 28 | 29 | file { "${elasticsearch::homedir}/scripts/${basefilename}": 30 | ensure => $ensure, 31 | source => $source, 32 | owner => $elasticsearch::elasticsearch_user, 33 | group => $elasticsearch::elasticsearch_group, 34 | recurse => $recurse, 35 | mode => '0644', 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /manifests/service.pp: -------------------------------------------------------------------------------- 1 | # This class exists to coordinate all service management related actions, 2 | # functionality and logical units in a central place. 3 | # 4 | # *Note*: "service" is the Puppet term and type for background processes 5 | # in general and is used in a platform-independent way. E.g. "service" means 6 | # "daemon" in relation to Unix-like systems. 7 | # 8 | # @author Richard Pijnenburg 9 | # @author Tyler Langlois 10 | # @author Gavin Williams 11 | # 12 | class elasticsearch::service { 13 | #### Service management 14 | 15 | if $elasticsearch::ensure == 'present' { 16 | case $elasticsearch::status { 17 | # make sure service is currently running, start it on boot 18 | 'enabled': { 19 | $_service_ensure = 'running' 20 | $_service_enable = true 21 | } 22 | # make sure service is currently stopped, do not start it on boot 23 | 'disabled': { 24 | $_service_ensure = 'stopped' 25 | $_service_enable = false 26 | } 27 | # make sure service is currently running, do not start it on boot 28 | 'running': { 29 | $_service_ensure = 'running' 30 | $_service_enable = false 31 | } 32 | # do not start service on boot, do not care whether currently running 33 | # or not 34 | 'unmanaged': { 35 | $_service_ensure = undef 36 | $_service_enable = false 37 | } 38 | default: { 39 | } 40 | } 41 | } else { 42 | # make sure the service is stopped and disabled (the removal itself will be 43 | # done by package.pp) 44 | $_service_ensure = 'stopped' 45 | $_service_enable = false 46 | } 47 | 48 | service { $elasticsearch::service_name: 49 | ensure => $_service_ensure, 50 | enable => $_service_enable, 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /manifests/user.pp: -------------------------------------------------------------------------------- 1 | # Manages x-pack users. 2 | # 3 | # @example creates and manage a user with membership in the 'logstash' and 'kibana4' roles. 4 | # elasticsearch::user { 'bob': 5 | # password => 'foobar', 6 | # roles => ['logstash', 'kibana4'], 7 | # } 8 | # 9 | # @param ensure 10 | # Whether the user should be present or not. 11 | # Set to `absent` to ensure a user is not installed 12 | # 13 | # @param password 14 | # Password for the given user. A plaintext password will be managed 15 | # with the esusers utility and requires a refresh to update, while 16 | # a hashed password from the esusers utility will be managed manually 17 | # in the uses file. 18 | # 19 | # @param roles 20 | # A list of roles to which the user should belong. 21 | # 22 | # @author Tyler Langlois 23 | # @author Gavin Williams 24 | # 25 | define elasticsearch::user ( 26 | String $password, 27 | Enum['absent', 'present'] $ensure = 'present', 28 | Array $roles = [], 29 | ) { 30 | if $password =~ /^\$2a\$/ { 31 | elasticsearch_user_file { $name: 32 | ensure => $ensure, 33 | configdir => $elasticsearch::configdir, 34 | hashed_password => $password, 35 | before => Elasticsearch_user_roles[$name], 36 | } 37 | } else { 38 | elasticsearch_user { $name: 39 | ensure => $ensure, 40 | configdir => $elasticsearch::configdir, 41 | password => $password, 42 | before => Elasticsearch_user_roles[$name], 43 | } 44 | } 45 | 46 | elasticsearch_user_roles { $name: 47 | ensure => $ensure, 48 | roles => $roles, 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-elasticsearch", 3 | "version": "9.0.1-rc0", 4 | "source": "https://github.com/voxpupuli/puppet-elasticsearch", 5 | "author": "voxpupuli@groups.io", 6 | "license": "Apache-2.0", 7 | "summary": "Module for managing and configuring Elasticsearch nodes", 8 | "project_page": "https://github.com/voxpupuli/puppet-elasticsearch", 9 | "issues_url": "https://github.com/voxpupuli/puppet-elasticsearch/issues", 10 | "dependencies": [ 11 | { 12 | "name": "puppet/elastic_stack", 13 | "version_requirement": ">= 8.0.0 < 10.0.0" 14 | }, 15 | { 16 | "name": "puppetlabs/java", 17 | "version_requirement": ">= 1.0.0 < 11.0.0" 18 | }, 19 | { 20 | "name": "puppetlabs/java_ks", 21 | "version_requirement": ">= 1.5.0 < 6.0.0" 22 | }, 23 | { 24 | "name": "puppetlabs/stdlib", 25 | "version_requirement": ">= 6.1.0 < 10.0.0" 26 | } 27 | ], 28 | "operatingsystem_support": [ 29 | { 30 | "operatingsystem": "RedHat", 31 | "operatingsystemrelease": [ 32 | "7", 33 | "8" 34 | ] 35 | }, 36 | { 37 | "operatingsystem": "CentOS", 38 | "operatingsystemrelease": [ 39 | "7", 40 | "8" 41 | ] 42 | }, 43 | { 44 | "operatingsystem": "OracleLinux", 45 | "operatingsystemrelease": [ 46 | "7", 47 | "8" 48 | ] 49 | }, 50 | { 51 | "operatingsystem": "Scientific", 52 | "operatingsystemrelease": [ 53 | "7", 54 | "8" 55 | ] 56 | }, 57 | { 58 | "operatingsystem": "Debian", 59 | "operatingsystemrelease": [ 60 | "11" 61 | ] 62 | }, 63 | { 64 | "operatingsystem": "Ubuntu", 65 | "operatingsystemrelease": [ 66 | "20.04", 67 | "22.04" 68 | ] 69 | }, 70 | { 71 | "operatingsystem": "SLES", 72 | "operatingsystemrelease": [ 73 | "12" 74 | ] 75 | } 76 | ], 77 | "requirements": [ 78 | { 79 | "name": "puppet", 80 | "version_requirement": ">= 7.0.0 < 9.0.0" 81 | } 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /spec/classes/010_elasticsearch_init_unkown_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'elasticsearch', type: 'class' do 6 | context 'on an unknown OS' do 7 | context 'it should fail' do 8 | let(:facts) do 9 | { operatingsystem: 'Windows' } 10 | end 11 | 12 | it { is_expected.to raise_error(Puppet::Error) } 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/classes/099_coverage_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | at_exit { RSpec::Puppet::Coverage.report! 100 } 4 | -------------------------------------------------------------------------------- /spec/defines/006_elasticsearch_script_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'elasticsearch::script', type: 'define' do 6 | let(:title) { 'foo' } 7 | let(:pre_condition) do 8 | %( 9 | class { "elasticsearch": 10 | config => { 11 | "node" => {"name" => "test" } 12 | } 13 | } 14 | ) 15 | end 16 | 17 | on_supported_os( 18 | hardwaremodels: ['x86_64'], 19 | supported_os: [ 20 | { 21 | 'operatingsystem' => 'CentOS', 22 | 'operatingsystemrelease' => ['6'] 23 | } 24 | ] 25 | ).each do |os, facts| 26 | context "on #{os}" do 27 | let(:facts) do 28 | facts.merge( 29 | scenario: '', 30 | common: '' 31 | ) 32 | end 33 | 34 | describe 'missing parent class' do 35 | it { is_expected.not_to compile } 36 | end 37 | 38 | describe 'adding script files' do 39 | let(:params) do 40 | { 41 | ensure: 'present', 42 | source: 'puppet:///path/to/foo.groovy' 43 | } 44 | end 45 | 46 | it { is_expected.to contain_elasticsearch__script('foo') } 47 | 48 | it { 49 | expect(subject).to contain_file('/usr/share/elasticsearch/scripts/foo.groovy'). 50 | with( 51 | source: 'puppet:///path/to/foo.groovy', 52 | ensure: 'present' 53 | ) 54 | } 55 | end 56 | 57 | describe 'adding script directories' do 58 | let(:params) do 59 | { 60 | ensure: 'directory', 61 | source: 'puppet:///path/to/my_scripts', 62 | recurse: 'remote' 63 | } 64 | end 65 | 66 | it { is_expected.to contain_elasticsearch__script('foo') } 67 | 68 | it { 69 | expect(subject).to contain_file( 70 | '/usr/share/elasticsearch/scripts/my_scripts' 71 | ).with( 72 | ensure: 'directory', 73 | source: 'puppet:///path/to/my_scripts', 74 | recurse: 'remote' 75 | ) 76 | } 77 | end 78 | 79 | describe 'removing scripts' do 80 | let(:params) do 81 | { 82 | ensure: 'absent', 83 | source: 'puppet:///path/to/foo.groovy' 84 | } 85 | end 86 | 87 | it { is_expected.to contain_elasticsearch__script('foo') } 88 | 89 | it { 90 | expect(subject).to contain_file('/usr/share/elasticsearch/scripts/foo.groovy'). 91 | with( 92 | source: 'puppet:///path/to/foo.groovy', 93 | ensure: 'absent' 94 | ) 95 | } 96 | end 97 | end 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /spec/defines/007_elasticsearch_user_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'helpers/class_shared_examples' 5 | 6 | describe 'elasticsearch::user' do 7 | let(:title) { 'elastic' } 8 | 9 | let(:pre_condition) do 10 | <<-EOS 11 | class { 'elasticsearch': } 12 | EOS 13 | end 14 | 15 | on_supported_os( 16 | hardwaremodels: ['x86_64'], 17 | supported_os: [ 18 | { 19 | 'operatingsystem' => 'CentOS', 20 | 'operatingsystemrelease' => ['7'] 21 | } 22 | ] 23 | ).each do |os, facts| 24 | context "on #{os}" do 25 | let(:facts) do 26 | facts.merge( 27 | scenario: '', 28 | common: '' 29 | ) 30 | end 31 | 32 | context 'with default parameters' do 33 | let(:params) do 34 | { 35 | password: 'foobar', 36 | roles: %w[monitor user] 37 | } 38 | end 39 | 40 | it { is_expected.to contain_elasticsearch__user('elastic') } 41 | it { is_expected.to contain_elasticsearch_user('elastic') } 42 | 43 | it do 44 | expect(subject).to contain_elasticsearch_user_roles('elastic').with( 45 | 'ensure' => 'present', 46 | 'roles' => %w[monitor user] 47 | ) 48 | end 49 | end 50 | 51 | describe 'collector ordering' do 52 | let(:pre_condition) do 53 | <<-EOS 54 | class { 'elasticsearch': } 55 | elasticsearch::template { 'foo': content => {"foo" => "bar"} } 56 | elasticsearch::role { 'test_role': 57 | privileges => { 58 | 'cluster' => 'monitor', 59 | 'indices' => { 60 | '*' => 'all', 61 | }, 62 | }, 63 | } 64 | EOS 65 | end 66 | 67 | let(:params) do 68 | { 69 | password: 'foobar', 70 | roles: %w[monitor user] 71 | } 72 | end 73 | 74 | it { is_expected.to contain_elasticsearch__role('test_role') } 75 | it { is_expected.to contain_elasticsearch_role('test_role') } 76 | it { is_expected.to contain_elasticsearch_role_mapping('test_role') } 77 | 78 | it { 79 | expect(subject).to contain_elasticsearch__user('elastic'). 80 | that_comes_before([ 81 | 'Elasticsearch::Template[foo]' 82 | ]).that_requires([ 83 | 'Elasticsearch::Role[test_role]' 84 | ]) 85 | } 86 | 87 | include_examples 'class', :systemd 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /spec/defines/012_elasticsearch_index_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'elasticsearch::index', type: 'define' do 6 | let(:title) { 'test-index' } 7 | let(:pre_condition) do 8 | 'class { "elasticsearch" : }' 9 | end 10 | 11 | on_supported_os( 12 | hardwaremodels: ['x86_64'], 13 | supported_os: [ 14 | { 15 | 'operatingsystem' => 'CentOS', 16 | 'operatingsystemrelease' => ['6'] 17 | } 18 | ] 19 | ).each do |os, facts| 20 | context "on #{os}" do 21 | let(:facts) do 22 | facts.merge( 23 | scenario: '', 24 | common: '' 25 | ) 26 | end 27 | 28 | describe 'parameter validation' do 29 | %i[api_ca_file api_ca_path].each do |param| 30 | let :params do 31 | { 32 | :ensure => 'present', 33 | param => 'foo/cert' 34 | } 35 | end 36 | 37 | it 'validates cert paths' do 38 | expect(subject).to compile.and_raise_error(%r{expects a}) 39 | end 40 | end 41 | 42 | describe 'missing parent class' do 43 | it { is_expected.not_to compile } 44 | end 45 | end 46 | 47 | describe 'class parameter inheritance' do 48 | let :params do 49 | { 50 | ensure: 'present' 51 | } 52 | end 53 | let(:pre_condition) do 54 | <<-EOS 55 | class { 'elasticsearch' : 56 | api_protocol => 'https', 57 | api_host => '127.0.0.1', 58 | api_port => 9201, 59 | api_timeout => 11, 60 | api_basic_auth_username => 'elastic', 61 | api_basic_auth_password => 'password', 62 | api_ca_file => '/foo/bar.pem', 63 | api_ca_path => '/foo/', 64 | validate_tls => false, 65 | } 66 | EOS 67 | end 68 | 69 | it do 70 | expect(subject).to contain_elasticsearch__index(title) 71 | expect(subject).to contain_es_instance_conn_validator( 72 | "#{title}-index-conn-validator" 73 | ).that_comes_before("elasticsearch_index[#{title}]") 74 | expect(subject).to contain_elasticsearch_index(title).with( 75 | ensure: 'present', 76 | settings: {}, 77 | protocol: 'https', 78 | host: '127.0.0.1', 79 | port: 9201, 80 | timeout: 11, 81 | username: 'elastic', 82 | password: 'password', 83 | ca_file: '/foo/bar.pem', 84 | ca_path: '/foo/', 85 | validate_tls: false 86 | ) 87 | end 88 | end 89 | 90 | describe 'index deletion' do 91 | let :params do 92 | { 93 | ensure: 'absent' 94 | } 95 | end 96 | 97 | it 'removes indices' do 98 | expect(subject).to contain_elasticsearch_index(title).with(ensure: 'absent') 99 | end 100 | end 101 | end 102 | end 103 | end 104 | -------------------------------------------------------------------------------- /spec/fixtures/artifacts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxpupuli/puppet-elasticsearch/aaf9d978a0c19033b34150cf50ce1e4baad677bd/spec/fixtures/artifacts/.gitkeep -------------------------------------------------------------------------------- /spec/fixtures/artifacts/plugins/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxpupuli/puppet-elasticsearch/aaf9d978a0c19033b34150cf50ce1e4baad677bd/spec/fixtures/artifacts/plugins/.gitkeep -------------------------------------------------------------------------------- /spec/fixtures/data/common.yaml: -------------------------------------------------------------------------------- 1 | --- {} 2 | -------------------------------------------------------------------------------- /spec/fixtures/data/composabletemplate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::component_templates: 3 | b1: 4 | content: 5 | template: 6 | mappings: 7 | properties: 8 | baz1: 9 | type: keyword 10 | 11 | elasticsearch::index_templates: 12 | foo: 13 | ensure: 'present' 14 | content: 15 | index_patterns: 16 | - foo-* 17 | baz: 18 | ensure: 'present' 19 | content: 20 | index_patterns: 21 | - baz-* 22 | template: 23 | settings: 24 | index: 25 | number_of_replicas: 1 26 | mappings: 27 | _source: 28 | enabled: true 29 | properties: 30 | host_name: 31 | type: keyword 32 | created_at: 33 | type: date 34 | format: "EEE MMM dd HH:mm:ss Z yyyy" 35 | composed_of: 36 | - b1 37 | priority: 10 38 | version: 3 39 | _meta: 40 | description: "my custom" 41 | -------------------------------------------------------------------------------- /spec/fixtures/data/envs/defaultinstance-merged.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | lookup_options: 3 | elasticsearch::instances: 4 | merge: deep 5 | elasticsearch::instances: 6 | default: 7 | config: 8 | node.name: default 9 | http.bind_host: 0.0.0.0 10 | -------------------------------------------------------------------------------- /spec/fixtures/data/envs/defaultinstance.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::instances: 3 | default: 4 | config: 5 | node.name: default 6 | http.bind_host: 0.0.0.0 7 | -------------------------------------------------------------------------------- /spec/fixtures/data/multipleinstances.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::instances: 3 | es-hiera-multiple-1: 4 | config: 5 | node.name: es-hiera-multiple-1 6 | http.bind_host: 0.0.0.0 7 | es-hiera-multiple-2: 8 | config: 9 | node.name: es-hiera-multiple-2 10 | http.bind_host: 0.0.0.0 11 | -------------------------------------------------------------------------------- /spec/fixtures/data/singleilmpolicy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::ilm_policies: 3 | mypolicy: 4 | ensure: 'present' 5 | content: 6 | policy: 7 | phases: 8 | warm: 9 | min_age: '2d' 10 | actions: 11 | shrink: 12 | number_of_shards: 1 13 | forcemerge: 14 | max_num_segments: 1 15 | cold: 16 | min_age: '30d' 17 | -------------------------------------------------------------------------------- /spec/fixtures/data/singleindex.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::indices: 3 | baz: 4 | ensure: present 5 | settings: 6 | index: 7 | number_of_shards: 1 8 | -------------------------------------------------------------------------------- /spec/fixtures/data/singleinstance.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::instances: 3 | es-hiera-single: 4 | config: 5 | node.name: es-hiera-single 6 | http.bind_host: 0.0.0.0 7 | -------------------------------------------------------------------------------- /spec/fixtures/data/singlepipeline.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::pipelines: 3 | testpipeline: 4 | ensure: present 5 | content: 6 | description: Add the foo field 7 | processors: 8 | - set: 9 | field: foo 10 | value: bar 11 | -------------------------------------------------------------------------------- /spec/fixtures/data/singleplugin.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::plugins: 3 | mobz/elasticsearch-head: 4 | ensure: present 5 | module_dir: head 6 | -------------------------------------------------------------------------------- /spec/fixtures/data/singlerole.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::roles: 3 | admin: 4 | ensure: present 5 | privileges: 6 | cluster: monitor 7 | indices: 8 | "*": all 9 | mappings: 10 | - cn=users,dc=example,dc=com 11 | -------------------------------------------------------------------------------- /spec/fixtures/data/singlescript.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::scripts: 3 | myscript: 4 | ensure: present 5 | source: puppet:///file/here 6 | -------------------------------------------------------------------------------- /spec/fixtures/data/singleslmpolicy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::slm_policies: 3 | mypolicy: 4 | ensure: 'present' 5 | content: 6 | name: 7 | schedule: 0 30 1 * * ? 8 | repository: backup 9 | config: {} 10 | retention: 11 | expire_after: 60d 12 | min_count: 2 13 | max_count: 10 14 | -------------------------------------------------------------------------------- /spec/fixtures/data/singletemplate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::templates: 3 | foo: 4 | ensure: present 5 | content: 6 | template: foo-* 7 | settings: 8 | index: 9 | number_of_replicas: 0 10 | -------------------------------------------------------------------------------- /spec/fixtures/data/singleuser.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch::users: 3 | elastic: 4 | ensure: present 5 | password: password 6 | roles: 7 | - admin 8 | -------------------------------------------------------------------------------- /spec/fixtures/facts/Warlock-nodes.json: -------------------------------------------------------------------------------- 1 | {"cluster_name":"elasticsearch","nodes":{"yQAWBO3FS8CupZnSvAVziQ":{"name":"Warlock","transport_address":"inet[/192.168.100.40:9300]","host":"devel01","ip":"192.168.100.40","version":"1.4.2","build":"927caff","http_address":"inet[/192.168.100.40:9200]","settings":{"path":{"data":"/var/lib/elasticsearch","work":"/tmp/elasticsearch","home":"/usr/share/elasticsearch","conf":"/etc/elasticsearch","logs":"/var/log/elasticsearch"},"pidfile":"/var/run/elasticsearch.pid","cluster":{"name":"elasticsearch"},"config":"/etc/elasticsearch/elasticsearch.yml","client":{"type":"node"},"name":"Warlock"},"os":{"refresh_interval_in_millis":1000,"available_processors":2,"cpu":{"vendor":"Intel","model":"Common KVM processor","mhz":3399,"total_cores":2,"total_sockets":1,"cores_per_socket":2,"cache_size_in_bytes":4096},"mem":{"total_in_bytes":2099183616},"swap":{"total_in_bytes":2145382400}},"process":{"refresh_interval_in_millis":1000,"id":20638,"max_file_descriptors":65535,"mlockall":false},"jvm":{"pid":20638,"version":"1.7.0_55","vm_name":"OpenJDK 64-Bit Server VM","vm_version":"24.51-b03","vm_vendor":"Oracle Corporation","start_time_in_millis":1421686713108,"mem":{"heap_init_in_bytes":268435456,"heap_max_in_bytes":1056309248,"non_heap_init_in_bytes":24313856,"non_heap_max_in_bytes":224395264,"direct_max_in_bytes":1056309248},"gc_collectors":["ParNew","ConcurrentMarkSweep"],"memory_pools":["Code Cache","Par Eden Space","Par Survivor Space","CMS Old Gen","CMS Perm Gen"]},"thread_pool":{"generic":{"type":"cached","keep_alive":"30s","queue_size":-1},"index":{"type":"fixed","min":2,"max":2,"queue_size":"200"},"bench":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"get":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"snapshot":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"merge":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"suggest":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"bulk":{"type":"fixed","min":2,"max":2,"queue_size":"50"},"optimize":{"type":"fixed","min":1,"max":1,"queue_size":-1},"warmer":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"flush":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"search":{"type":"fixed","min":6,"max":6,"queue_size":"1k"},"listener":{"type":"fixed","min":1,"max":1,"queue_size":-1},"percolate":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"management":{"type":"scaling","min":1,"max":5,"keep_alive":"5m","queue_size":-1},"refresh":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1}},"network":{"refresh_interval_in_millis":5000,"primary_interface":{"address":"192.168.100.40","name":"eth0","mac_address":"9E:FA:5C:B8:CC:4D"}},"transport":{"bound_address":"inet[/0:0:0:0:0:0:0:0:9300]","publish_address":"inet[/192.168.100.40:9300]"},"http":{"bound_address":"inet[/0:0:0:0:0:0:0:0:9200]","publish_address":"inet[/192.168.100.40:9200]","max_content_length_in_bytes":104857600},"plugins":[{"name":"kopf","version":"1.4.3","description":"kopf - simple web administration tool for ElasticSearch","url":"/_plugin/kopf/","jvm":false,"site":true}]}}} 2 | -------------------------------------------------------------------------------- /spec/fixtures/facts/Warlock-root.json: -------------------------------------------------------------------------------- 1 | { 2 | "status" : 200, 3 | "name" : "Warlock", 4 | "cluster_name" : "elasticsearch", 5 | "version" : { 6 | "number" : "1.4.2", 7 | "build_hash" : "927caff6f05403e936c20bf4529f144f0c89fd8c", 8 | "build_timestamp" : "2014-12-16T14:11:12Z", 9 | "build_snapshot" : false, 10 | "lucene_version" : "4.10.2" 11 | }, 12 | "tagline" : "You Know, for Search" 13 | } 14 | -------------------------------------------------------------------------------- /spec/fixtures/facts/Zom-nodes.json: -------------------------------------------------------------------------------- 1 | {"cluster_name":"elasticsearch","nodes":{"yQAWBO3FS8CupZnSvAVziQ":{"name":"Zom","transport_address":"inet[/192.168.100.40:9300]","host":"devel01","ip":"192.168.100.40","version":"1.4.2","build":"927caff","http_address":"inet[/192.168.100.40:9200]","settings":{"path":{"data":"/var/lib/elasticsearch","work":"/tmp/elasticsearch","home":"/usr/share/elasticsearch","conf":"/etc/elasticsearch","logs":"/var/log/elasticsearch"},"pidfile":"/var/run/elasticsearch.pid","cluster":{"name":"elasticsearch"},"config":"/etc/elasticsearch/elasticsearch.yml","client":{"type":"node"},"name":"Zom"},"os":{"refresh_interval_in_millis":1000,"available_processors":2,"cpu":{"vendor":"Intel","model":"Common KVM processor","mhz":3399,"total_cores":2,"total_sockets":1,"cores_per_socket":2,"cache_size_in_bytes":4096},"mem":{"total_in_bytes":2099183616},"swap":{"total_in_bytes":2145382400}},"process":{"refresh_interval_in_millis":1000,"id":20638,"max_file_descriptors":65535,"mlockall":false},"jvm":{"pid":20638,"version":"1.7.0_55","vm_name":"OpenJDK 64-Bit Server VM","vm_version":"24.51-b03","vm_vendor":"Oracle Corporation","start_time_in_millis":1421686713108,"mem":{"heap_init_in_bytes":268435456,"heap_max_in_bytes":1056309248,"non_heap_init_in_bytes":24313856,"non_heap_max_in_bytes":224395264,"direct_max_in_bytes":1056309248},"gc_collectors":["ParNew","ConcurrentMarkSweep"],"memory_pools":["Code Cache","Par Eden Space","Par Survivor Space","CMS Old Gen","CMS Perm Gen"]},"thread_pool":{"generic":{"type":"cached","keep_alive":"30s","queue_size":-1},"index":{"type":"fixed","min":2,"max":2,"queue_size":"200"},"bench":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"get":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"snapshot":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"merge":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"suggest":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"bulk":{"type":"fixed","min":2,"max":2,"queue_size":"50"},"optimize":{"type":"fixed","min":1,"max":1,"queue_size":-1},"warmer":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"flush":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"search":{"type":"fixed","min":6,"max":6,"queue_size":"1k"},"listener":{"type":"fixed","min":1,"max":1,"queue_size":-1},"percolate":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"management":{"type":"scaling","min":1,"max":5,"keep_alive":"5m","queue_size":-1},"refresh":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1}},"network":{"refresh_interval_in_millis":5000,"primary_interface":{"address":"192.168.100.40","name":"eth0","mac_address":"9E:FA:5C:B8:CC:4D"}},"transport":{"bound_address":"inet[/0:0:0:0:0:0:0:0:9300]","publish_address":"inet[/192.168.100.40:9300]"},"http":{"bound_address":"inet[/0:0:0:0:0:0:0:0:9200]","publish_address":"inet[/192.168.100.40:9200]","max_content_length_in_bytes":104857600},"plugins":[{"name":"kopf","version":"1.4.3","description":"kopf - simple web administration tool for ElasticSearch","url":"/_plugin/kopf/","jvm":false,"site":true}]}}} 2 | -------------------------------------------------------------------------------- /spec/fixtures/facts/Zom-root.json: -------------------------------------------------------------------------------- 1 | { 2 | "status" : 200, 3 | "name" : "Zom", 4 | "cluster_name" : "elasticsearch", 5 | "version" : { 6 | "number" : "1.4.2", 7 | "build_hash" : "927caff6f05403e936c20bf4529f144f0c89fd8c", 8 | "build_timestamp" : "2014-12-16T14:11:12Z", 9 | "build_snapshot" : false, 10 | "lucene_version" : "4.10.2" 11 | }, 12 | "tagline" : "You Know, for Search" 13 | } 14 | -------------------------------------------------------------------------------- /spec/fixtures/hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 5 3 | hierarchy: 4 | - name: Spec-Fixtures 5 | paths: 6 | # Default for datadir is data/ (relative to hiera.yaml's Directory) 7 | - ! "%{::facts.scenario}.yaml" 8 | - envs/%{::facts.common}.yaml 9 | - common.yaml 10 | -------------------------------------------------------------------------------- /spec/fixtures/ilm_policies/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "policy" : { 3 | "phases" : { 4 | "warm" : { 5 | "min_age" : "2d", 6 | "actions" : { 7 | "shrink" : { 8 | "number_of_shards" : 1 9 | }, 10 | "forcemerge" : { 11 | "max_num_segments" : 1 12 | } 13 | } 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/fixtures/pipelines/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "An example pipeline.", 3 | "on_failure": [ 4 | { 5 | "set": { 6 | "field": "error", 7 | "value": "{{ _ingest.on_failure_message }}" 8 | } 9 | } 10 | ], 11 | "processors": [ 12 | { 13 | "grok": { 14 | "field": "message", 15 | "ignore_missing": true, 16 | "patterns": [ 17 | "%{COMBINEDAPACHELOG}" 18 | ] 19 | } 20 | }, 21 | { 22 | "remove": { 23 | "field": "message" 24 | } 25 | }, 26 | { 27 | "date": { 28 | "field": "read_timestamp", 29 | "formats": [ 30 | "dd/MMM/YYYY:H:m:s Z" 31 | ], 32 | "target_field": "@timestamp" 33 | } 34 | }, 35 | { 36 | "remove": { 37 | "field": "read_timestamp" 38 | } 39 | }, 40 | { 41 | "script": { 42 | "lang": "painless", 43 | "source": "ctx._index = 'foo';" 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /spec/fixtures/slm_policies/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "", 3 | "schedule" : "0 30 1 * * ?", 4 | "repository" : "backup", 5 | "config" : { }, 6 | "retention" : { 7 | "expire_after" : "60d", 8 | "min_count" : 2, 9 | "max_count" : 10 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/fixtures/templates/6.x.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": [ "logstash-*" ], 3 | "version": 123, 4 | "settings": { 5 | "index": { 6 | "refresh_interval": "5s", 7 | "analysis": { 8 | "analyzer": { 9 | "default": { 10 | "type": "standard", 11 | "stopwords": "_none_" 12 | } 13 | } 14 | } 15 | } 16 | }, 17 | "mappings": { 18 | "_doc": { 19 | "dynamic_templates": [ 20 | { 21 | "string_fields": { 22 | "match": "*", 23 | "match_mapping_type": "string", 24 | "mapping": { 25 | "type": "multi_field", 26 | "fields": { 27 | "{name}": { 28 | "type": "text", 29 | "index": "analyzed", 30 | "omit_norms": true 31 | }, 32 | "raw": { 33 | "type ": "text", 34 | "index": "not_analyzed", 35 | "ignore_above": 256 36 | } 37 | } 38 | } 39 | } 40 | } 41 | ], 42 | "properties": { 43 | "@version": { 44 | "type": "text", 45 | "index": false 46 | }, 47 | "geoip": { 48 | "type": "object", 49 | "dynamic": true, 50 | "properties": { 51 | "location": { 52 | "type": "geo_point" 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /spec/fixtures/templates/7.x.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": [ "logstash-*" ], 3 | "version": 123, 4 | "settings": { 5 | "index": { 6 | "refresh_interval": "5s", 7 | "analysis": { 8 | "analyzer": { 9 | "default": { 10 | "type": "standard", 11 | "stopwords": "_none_" 12 | } 13 | } 14 | } 15 | } 16 | }, 17 | "mappings": { 18 | "dynamic_templates": [ 19 | { 20 | "string_fields": { 21 | "match": "*", 22 | "match_mapping_type": "string", 23 | "mapping": { 24 | "type": "multi_field", 25 | "fields": { 26 | "{name}": { 27 | "type": "text", 28 | "index": "analyzed", 29 | "omit_norms": true 30 | }, 31 | "raw": { 32 | "type ": "text", 33 | "index": "not_analyzed", 34 | "ignore_above": 256 35 | } 36 | } 37 | } 38 | } 39 | } 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /spec/fixtures/templates/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "mappings": { 4 | "properties": { 5 | "dummy": { 6 | "type": "keyword" 7 | } 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/fixtures/templates/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": ["foo*", "bar*", "baz*"], 3 | "template": { 4 | "settings": { 5 | "index": { 6 | "refresh_interval": "5s" 7 | } 8 | }, 9 | "mappings": { 10 | "_source": { 11 | "enabled": true 12 | }, 13 | "properties": { 14 | "host_name": { 15 | "type": "keyword" 16 | }, 17 | "created_at": { 18 | "type": "date", 19 | "format": "EEE MMM dd HH:mm:ss Z yyyy" 20 | } 21 | } 22 | }, 23 | "aliases": { 24 | "mydata": { } 25 | } 26 | }, 27 | "priority": 500, 28 | "composed_of": [], 29 | "version": 3, 30 | "_meta": { 31 | "description": "my custom" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /spec/fixtures/templates/post_8.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": ["te*", "bar*"], 3 | "template": { 4 | "settings": { 5 | "number_of_shards": 1 6 | }, 7 | "mappings": { 8 | "_source": { 9 | "enabled": false 10 | }, 11 | "properties": { 12 | "host_name": { 13 | "type": "keyword" 14 | }, 15 | "created_at": { 16 | "type": "date", 17 | "format": "EEE MMM dd HH:mm:ss Z yyyy" 18 | } 19 | } 20 | }, 21 | "aliases": { 22 | "mydata": { } 23 | } 24 | }, 25 | "priority": 10, 26 | "version": 3, 27 | "_meta": { 28 | "description": "my custom" 29 | } 30 | } -------------------------------------------------------------------------------- /spec/functions/es_plugin_name_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'es_plugin_name' do 6 | describe 'exception handling' do 7 | it { 8 | expect(subject).to run.with_params.and_raise_error( 9 | Puppet::ParseError, %r{wrong number of arguments}i 10 | ) 11 | } 12 | end 13 | 14 | describe 'single arguments' do 15 | it { 16 | expect(subject).to run. 17 | with_params('foo'). 18 | and_return('foo') 19 | } 20 | 21 | it { 22 | expect(subject).to run. 23 | with_params('vendor/foo'). 24 | and_return('foo') 25 | } 26 | 27 | it { 28 | expect(subject).to run. 29 | with_params('vendor/foo/1.0.0'). 30 | and_return('foo') 31 | } 32 | 33 | it { 34 | expect(subject).to run. 35 | with_params('vendor/es-foo/1.0.0'). 36 | and_return('foo') 37 | } 38 | 39 | it { 40 | expect(subject).to run. 41 | with_params('vendor/elasticsearch-foo/1.0.0'). 42 | and_return('foo') 43 | } 44 | 45 | it { 46 | expect(subject).to run. 47 | with_params('com.foo:plugin_name:5.2.0'). 48 | and_return('plugin_name') 49 | } 50 | 51 | it { 52 | expect(subject).to run. 53 | with_params('com:plugin_name:5.2.0-12'). 54 | and_return('plugin_name') 55 | } 56 | 57 | it { 58 | expect(subject).to run. 59 | with_params('com.foo.bar:plugin_name:5'). 60 | and_return('plugin_name') 61 | } 62 | end 63 | 64 | describe 'multiple arguments' do 65 | it { 66 | expect(subject).to run. 67 | with_params('foo', nil). 68 | and_return('foo') 69 | } 70 | 71 | it { 72 | expect(subject).to run. 73 | with_params(nil, 'foo'). 74 | and_return('foo') 75 | } 76 | 77 | it { 78 | expect(subject).to run. 79 | with_params(nil, 0, 'foo', 'bar'). 80 | and_return('foo') 81 | } 82 | end 83 | 84 | describe 'undef parameters' do 85 | it { 86 | expect(subject).to run. 87 | with_params('', 'foo'). 88 | and_return('foo') 89 | } 90 | 91 | it { 92 | expect(subject).to run. 93 | with_params(''). 94 | and_raise_error(Puppet::Error, %r{could not}) 95 | } 96 | end 97 | 98 | it 'does not change the original values' do 99 | argument1 = 'foo' 100 | original1 = argument1.dup 101 | 102 | subject.execute(argument1) 103 | expect(argument1).to eq(original1) 104 | end 105 | end 106 | -------------------------------------------------------------------------------- /spec/functions/plugin_dir_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'plugin_dir' do 6 | describe 'exception handling' do 7 | describe 'with no arguments' do 8 | it { 9 | expect(subject).to run.with_params. 10 | and_raise_error(Puppet::ParseError) 11 | } 12 | end 13 | 14 | describe 'more than two arguments' do 15 | it { 16 | expect(subject).to run.with_params('a', 'b', 'c'). 17 | and_raise_error(Puppet::ParseError) 18 | } 19 | end 20 | 21 | describe 'non-string arguments' do 22 | it { 23 | expect(subject).to run.with_params([]). 24 | and_raise_error(Puppet::ParseError) 25 | } 26 | end 27 | end 28 | 29 | { 30 | 'mobz/elasticsearch-head' => 'head', 31 | 'lukas-vlcek/bigdesk/2.4.0' => 'bigdesk', 32 | 'elasticsearch/elasticsearch-cloud-aws/2.5.1' => 'cloud-aws', 33 | 'com.sksamuel.elasticsearch/elasticsearch-river-redis/1.1.0' => 'river-redis', 34 | 'com.github.lbroudoux.elasticsearch/amazon-s3-river/1.4.0' => 'amazon-s3-river', 35 | 'elasticsearch/elasticsearch-lang-groovy/2.0.0' => 'lang-groovy', 36 | 'royrusso/elasticsearch-hq' => 'hq', 37 | 'polyfractal/elasticsearch-inquisitor' => 'inquisitor', 38 | 'mycustomplugin' => 'mycustomplugin' 39 | }.each do |plugin, dir| 40 | describe "parsed dir for #{plugin}" do 41 | it { is_expected.to run.with_params(plugin).and_return(dir) } 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/bad_manifest_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'invalid manifest application' do 4 | context 'bad manifest' do 5 | let(:applied_manifest) do 6 | <<-MANIFEST 7 | class { 'elasticsearch' : 8 | #{manifest} 9 | #{defined?(manifest_class_parameters) && manifest_class_parameters} 10 | } 11 | 12 | #{defined?(extra_manifest) && extra_manifest} 13 | MANIFEST 14 | end 15 | 16 | it 'fails to apply' do 17 | apply_manifest(applied_manifest, expect_failures: true, debug: v[:puppet_debug]) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/basic_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/manifest_shared_examples' 5 | 6 | shared_examples 'basic acceptance tests' do |es_config| 7 | include_examples('manifest application') 8 | 9 | describe package("elasticsearch#{v[:oss] ? '-oss' : ''}") do 10 | it { 11 | expect(subject).to be_installed. 12 | with_version(v[:elasticsearch_full_version]) 13 | } 14 | end 15 | 16 | %w[ 17 | /etc/elasticsearch 18 | /usr/share/elasticsearch 19 | /var/lib/elasticsearch 20 | ].each do |dir| 21 | describe file(dir) do 22 | it { is_expected.to be_directory } 23 | end 24 | end 25 | 26 | describe 'resources' do 27 | describe service('elasticsearch') do 28 | it { send(es_config.empty? ? :should_not : :should, be_enabled) } 29 | it { send(es_config.empty? ? :should_not : :should, be_running) } 30 | end 31 | 32 | unless es_config.empty? 33 | describe file(pid_file) do 34 | it { is_expected.to be_file } 35 | its(:content) { is_expected.to match(%r{[0-9]+}) } 36 | end 37 | 38 | describe file('/etc/elasticsearch/elasticsearch.yml') do 39 | it { is_expected.to be_file } 40 | it { is_expected.to contain "name: #{es_config['node.name']}" } 41 | end 42 | end 43 | 44 | unless es_config.empty? 45 | es_port = es_config['http.port'] 46 | describe port(es_port) do 47 | it 'open', :with_retries do 48 | expect(subject).to be_listening 49 | end 50 | end 51 | 52 | describe "http://localhost:#{es_port}/_nodes/_local" do 53 | subject { shell("curl http://localhost:#{es_port}/_nodes/_local") } 54 | 55 | it 'serves requests', :with_retries do 56 | expect(subject.exit_code).to eq(0) 57 | end 58 | 59 | it 'uses the default data path', :with_retries do 60 | json = JSON.parse(subject.stdout)['nodes'].values.first 61 | data_dir = ['/var/lib/elasticsearch'] 62 | expect( 63 | json['settings']['path'] 64 | ).to include( 65 | 'data' => data_dir 66 | ) 67 | end 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/datadir_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/manifest_shared_examples' 5 | 6 | shared_examples 'datadir directory validation' do |es_config, datapaths| 7 | include_examples('manifest application') 8 | 9 | describe file('/etc/elasticsearch/elasticsearch.yml') do 10 | it { is_expected.to be_file } 11 | 12 | datapaths.each do |datapath| 13 | it { is_expected.to contain datapath } 14 | end 15 | end 16 | 17 | datapaths.each do |datapath| 18 | describe file(datapath) do 19 | it { is_expected.to be_directory } 20 | end 21 | end 22 | 23 | es_port = es_config['http.port'] 24 | describe port(es_port) do 25 | it 'open', :with_retries do 26 | expect(subject).to be_listening 27 | end 28 | end 29 | 30 | describe "http://localhost:#{es_port}/_nodes/_local" do 31 | subject { shell("curl http://localhost:#{es_port}/_nodes/_local") } 32 | 33 | it 'uses a custom data path' do 34 | json = JSON.parse(subject.stdout)['nodes'].values.first 35 | expect( 36 | json['settings']['path']['data'] 37 | ).to(datapaths.one? && v[:elasticsearch_major_version] <= 2 ? eq(datapaths.first) : match_array(datapaths)) 38 | end 39 | end 40 | end 41 | 42 | shared_examples 'datadir acceptance tests' do |es_config| 43 | describe 'elasticsearch::datadir' do 44 | let(:manifest_class_parameters) { 'restart_on_change => true' } 45 | 46 | context 'single path', :with_cleanup do 47 | let(:manifest_class_parameters) do 48 | <<-MANIFEST 49 | datadir => '/var/lib/elasticsearch-data', 50 | restart_on_change => true, 51 | MANIFEST 52 | end 53 | 54 | include_examples('datadir directory validation', 55 | es_config, 56 | ['/var/lib/elasticsearch-data']) 57 | end 58 | 59 | context 'multiple paths', :with_cleanup do 60 | let(:manifest_class_parameters) do 61 | <<-MANIFEST 62 | datadir => [ 63 | '/var/lib/elasticsearch-01', 64 | '/var/lib/elasticsearch-02' 65 | ], 66 | restart_on_change => true, 67 | MANIFEST 68 | end 69 | 70 | include_examples('datadir directory validation', 71 | es_config, 72 | ['/var/lib/elasticsearch-01', '/var/lib/elasticsearch-02']) 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/hiera_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'tempfile' 4 | require 'helpers/acceptance/tests/basic_shared_examples' 5 | require 'helpers/acceptance/tests/plugin_shared_examples' 6 | 7 | agents = only_host_with_role(hosts, 'agent') 8 | 9 | shared_examples 'hiera tests with' do |es_config, additional_yaml = {}| 10 | hieradata = { 11 | 'elasticsearch::config' => es_config 12 | }.merge(additional_yaml).to_yaml 13 | 14 | before :all do # rubocop:disable RSpec/BeforeAfterAll 15 | write_hieradata_to(agents, hieradata) 16 | end 17 | 18 | include_examples('basic acceptance tests', es_config) 19 | end 20 | 21 | shared_examples 'hiera acceptance tests' do |es_config, plugins| 22 | describe 'hiera', :then_purge do 23 | let(:manifest) do 24 | package = if v[:is_snapshot] 25 | <<-MANIFEST 26 | manage_repo => false, 27 | package_url => '#{v[:snapshot_package]}', 28 | MANIFEST 29 | else 30 | <<-MANIFEST 31 | # Hard version set here due to plugin incompatibilities. 32 | version => '#{v[:elasticsearch_full_version]}', 33 | MANIFEST 34 | end 35 | 36 | <<-MANIFEST 37 | api_timeout => 60, 38 | jvm_options => [ 39 | '-Xms128m', 40 | '-Xmx128m', 41 | ], 42 | oss => #{v[:oss]}, 43 | #{package} 44 | MANIFEST 45 | end 46 | 47 | let(:manifest_class_parameters) { 'restart_on_change => true' } 48 | 49 | after :all do # rubocop:disable RSpec/BeforeAfterAll 50 | write_hieradata_to(agents, {}) 51 | 52 | # Ensure that elasticsearch is cleaned up before any other tests 53 | cleanup_manifest = <<-EOS 54 | class { 'elasticsearch': ensure => 'absent', oss => #{v[:oss]} } 55 | EOS 56 | apply_manifest(cleanup_manifest, debug: v[:puppet_debug]) 57 | end 58 | 59 | describe 'with hieradata' do 60 | # Remove leading 0: 01234567 is valid octal, but 89abcdef is not and the 61 | # serialisation will cause trouble for the test suite (quoting the value?). 62 | nodename = SecureRandom.hex(10).sub(%r{^0+}, '') 63 | include_examples( 64 | 'hiera tests with', 65 | es_config.merge('node.name' => nodename) 66 | ) 67 | end 68 | 69 | plugins.each_pair do |plugin, _meta| 70 | describe "with plugin #{plugin}" do 71 | nodename = SecureRandom.hex(10) 72 | include_examples( 73 | 'hiera tests with', 74 | es_config.merge('node.name' => nodename), 75 | 'elasticsearch::plugins' => { 76 | plugin => { 77 | 'ensure' => 'present' 78 | } 79 | } 80 | ) 81 | 82 | include_examples( 83 | 'plugin API response', 84 | es_config.merge('node.name' => nodename), 85 | 'reports the plugin as installed', 86 | 'name' => plugin 87 | ) 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/manifest_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'manifest application' do |idempotency_check = true| 4 | context 'manifest' do 5 | let(:applied_manifest) do 6 | repo = if elastic_repo 7 | <<-MANIFEST 8 | class { 'elastic_stack::repo': 9 | oss => #{v[:oss]}, 10 | version => #{v[:elasticsearch_major_version]}, 11 | } 12 | MANIFEST 13 | else 14 | '' 15 | end 16 | 17 | <<-MANIFEST 18 | #{repo} 19 | 20 | class { 'elasticsearch' : 21 | #{manifest} 22 | #{defined?(manifest_class_parameters) && manifest_class_parameters} 23 | } 24 | 25 | #{defined?(extra_manifest) && extra_manifest} 26 | MANIFEST 27 | end 28 | 29 | it 'applies cleanly' do 30 | apply_manifest(applied_manifest, catch_failures: true, debug: v[:puppet_debug]) 31 | end 32 | 33 | # binding.pry 34 | if idempotency_check 35 | it 'is idempotent', :logs_on_failure do 36 | apply_manifest(applied_manifest, catch_changes: true, debug: v[:puppet_debug]) 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/package_url_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/basic_shared_examples' 5 | 6 | shared_examples 'package_url acceptance tests' do |es_config| 7 | describe 'elasticsearch::package_url' do 8 | # Override default manifest to remove `package` 9 | let(:manifest) do 10 | <<-MANIFEST 11 | api_timeout => 60, 12 | config => { 13 | #{es_config.map { |k, v| " '#{k}' => '#{v}'," }.join("\n")} 14 | }, 15 | jvm_options => [ 16 | '-Xms128m', 17 | '-Xmx128m', 18 | ], 19 | oss => #{v[:oss]}, 20 | MANIFEST 21 | end 22 | 23 | # context 'via http', :with_cleanup do 24 | context 'via http' do 25 | let(:manifest_class_parameters) do 26 | <<-MANIFEST 27 | manage_repo => false, 28 | package_url => '#{v[:elasticsearch_package][:url]}' 29 | MANIFEST 30 | end 31 | 32 | include_examples('basic acceptance tests', es_config) 33 | end 34 | 35 | context 'via local filesystem', :with_cleanup do 36 | before :all do # rubocop:disable RSpec/BeforeAfterAll 37 | scp_to default, 38 | v[:elasticsearch_package][:path], 39 | "/tmp/#{v[:elasticsearch_package][:filename]}" 40 | end 41 | 42 | let(:manifest_class_parameters) do 43 | <<-MANIFEST 44 | manage_repo => false, 45 | package_url => 'file:/tmp/#{v[:elasticsearch_package][:filename]}' 46 | MANIFEST 47 | end 48 | 49 | include_examples('basic acceptance tests', es_config) 50 | end 51 | 52 | context 'via puppet paths', :with_cleanup do 53 | before :all do # rubocop:disable RSpec/BeforeAfterAll 54 | shell "mkdir -p #{default.puppet['codedir']}/modules/another/files" 55 | 56 | scp_to default, 57 | v[:elasticsearch_package][:path], 58 | "#{default.puppet['codedir']}/modules/another/files/#{v[:elasticsearch_package][:filename]}" 59 | end 60 | 61 | let(:manifest_class_parameters) do 62 | <<-MANIFEST 63 | manage_repo => false, 64 | package_url => 'puppet:///modules/another/#{v[:elasticsearch_package][:filename]}', 65 | MANIFEST 66 | end 67 | 68 | include_examples('basic acceptance tests', es_config) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/pipeline_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/manifest_shared_examples' 5 | require 'helpers/acceptance/tests/bad_manifest_shared_examples' 6 | 7 | shared_examples 'pipeline operations' do |es_config, pipeline| 8 | describe 'pipeline resources' do 9 | let(:pipeline_name) { 'foo' } 10 | 11 | context 'present' do 12 | let(:extra_manifest) do 13 | <<-MANIFEST 14 | elasticsearch::pipeline { '#{pipeline_name}': 15 | ensure => 'present', 16 | content => #{pipeline} 17 | } 18 | MANIFEST 19 | end 20 | 21 | include_examples('manifest application') 22 | 23 | include_examples('pipeline content', es_config, pipeline) 24 | end 25 | 26 | context 'absent' do 27 | let(:extra_manifest) do 28 | <<-MANIFEST 29 | elasticsearch::template { '#{pipeline_name}': 30 | ensure => absent, 31 | } 32 | MANIFEST 33 | end 34 | 35 | include_examples('manifest application') 36 | end 37 | end 38 | end 39 | 40 | # Verifies the content of a loaded index template. 41 | shared_examples 'pipeline content' do |es_config, pipeline| 42 | elasticsearch_port = es_config['http.port'] 43 | describe port(elasticsearch_port) do 44 | it 'open', :with_retries do 45 | expect(subject).to be_listening 46 | end 47 | end 48 | 49 | describe "http://localhost:#{elasticsearch_port}/_ingest/pipeline" do 50 | subject { shell("curl http://localhost:#{elasticsearch_port}/_ingest/pipeline") } 51 | 52 | it 'returns the configured pipelines', :with_retries do 53 | expect(JSON.parse(subject.stdout).values). 54 | to include(include(pipeline)) 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/plugin_api_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | 5 | shared_examples 'plugin API response' do |es_config, desc, val| 6 | describe port(es_config['http.port']) do 7 | it 'open', :with_retries do 8 | expect(subject).to be_listening 9 | end 10 | end 11 | 12 | describe "http://localhost:#{es_config['http.port']}/_cluster/stats" do 13 | subject { shell("curl http://localhost:#{es_config['http.port']}/_cluster/stats") } 14 | 15 | it desc, :with_retries do 16 | expect( 17 | JSON.parse(subject.stdout)['nodes']['plugins'] 18 | ).to include(include(val)) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/plugin_upgrade_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/manifest_shared_examples' 5 | require 'helpers/acceptance/tests/plugin_api_shared_examples' 6 | 7 | shared_examples 'plugin upgrade acceptance tests' do |plugin| 8 | describe 'elasticsearch::plugin' do 9 | # Ensure that instances are restarted to include plugins 10 | let(:manifest_class_parameters) { 'restart_on_change => true' } 11 | 12 | instances = { 13 | 'es-01' => { 14 | 'config' => { 15 | 'http.port' => 9200, 16 | 'node.name' => 'elasticsearch001' 17 | } 18 | } 19 | } 20 | 21 | describe 'installation' do 22 | describe 'upgrades', :with_cleanup do 23 | context 'initial installation' do 24 | let(:extra_manifest) do 25 | <<-MANIFEST 26 | elasticsearch::plugin { '#{plugin[:repository]}-#{plugin[:name]}/v#{plugin[:initial]}': 27 | instances => 'es-01', 28 | } 29 | MANIFEST 30 | end 31 | 32 | include_examples( 33 | 'manifest application', 34 | instances 35 | ) 36 | 37 | include_examples( 38 | 'plugin API response', 39 | instances, 40 | 'contains the initial plugin version', 41 | 'name' => plugin[:name], 42 | 'version' => plugin[:initial] 43 | ) 44 | end 45 | 46 | describe 'upgrading' do 47 | let(:extra_manifest) do 48 | <<-MANIFEST 49 | elasticsearch::plugin { '#{plugin[:repository]}-#{plugin[:name]}/v#{plugin[:upgraded]}': 50 | instances => 'es-01', 51 | } 52 | MANIFEST 53 | end 54 | 55 | include_examples( 56 | 'manifest application', 57 | instances 58 | ) 59 | 60 | include_examples( 61 | 'plugin API response', 62 | instances, 63 | 'contains the upgraded plugin version', 64 | 'name' => plugin[:name], 65 | 'version' => plugin[:upgraded] 66 | ) 67 | end 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/removal_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'module removal' do |es_config| 4 | describe 'uninstalling' do 5 | let(:manifest) do 6 | <<-MANIFEST 7 | class { 'elasticsearch': ensure => 'absent', oss => #{v[:oss]} } 8 | MANIFEST 9 | end 10 | 11 | it 'runs successfully' do 12 | apply_manifest(manifest, catch_failures: true, debug: v[:puppet_debug]) 13 | end 14 | 15 | describe package("elasticsearch#{v[:oss] ? '-oss' : ''}") do 16 | it { is_expected.not_to be_installed } 17 | end 18 | 19 | describe service('elasticsearch') do 20 | it { is_expected.not_to be_enabled } 21 | it { is_expected.not_to be_running } 22 | end 23 | 24 | unless es_config.empty? 25 | describe port(es_config['http.port']) do 26 | it 'closed' do 27 | expect(subject).not_to be_listening 28 | end 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/snapshot_repository_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/manifest_shared_examples' 5 | 6 | # Main entrypoint for snapshot tests 7 | shared_examples 'snapshot repository acceptance tests' do 8 | describe 'elasticsearch::snapshot_repository', :with_cleanup do 9 | es_config = { 10 | 'http.port' => 9200, 11 | 'node.name' => 'elasticsearchSnapshot01', 12 | 'path.repo' => '/var/lib/elasticsearch' 13 | } 14 | 15 | # Override the manifest in order to populate 'path.repo' 16 | let(:manifest) do 17 | package = if v[:is_snapshot] 18 | <<-MANIFEST 19 | manage_repo => false, 20 | package_url => '#{v[:snapshot_package]}', 21 | MANIFEST 22 | else 23 | <<-MANIFEST 24 | # Hard version set here due to plugin incompatibilities. 25 | version => '#{v[:elasticsearch_full_version]}', 26 | MANIFEST 27 | end 28 | 29 | <<-MANIFEST 30 | api_timeout => 60, 31 | config => { 32 | #{es_config.map { |k, v| " '#{k}' => '#{v}'," }.join("\n")} 33 | }, 34 | jvm_options => [ 35 | '-Xms128m', 36 | '-Xmx128m', 37 | ], 38 | oss => #{v[:oss]}, 39 | #{package} 40 | MANIFEST 41 | end 42 | 43 | let(:manifest_class_parameters) { 'restart_on_change => true' } 44 | 45 | let(:extra_manifest) do 46 | <<-MANIFEST 47 | elasticsearch::snapshot_repository { 'backup': 48 | ensure => 'present', 49 | api_timeout => 60, 50 | location => '/var/lib/elasticsearch/backup', 51 | max_restore_rate => '20mb', 52 | max_snapshot_rate => '80mb', 53 | } 54 | MANIFEST 55 | end 56 | 57 | include_examples('manifest application', es_config) 58 | 59 | es_port = es_config['http.port'] 60 | describe port(es_port) do 61 | it 'open', :with_retries do 62 | expect(subject).to be_listening 63 | end 64 | end 65 | 66 | describe "http://localhost:#{es_port}/_snapshot/backup" do 67 | subject { shell("curl http://localhost:#{es_port}/_snapshot/backup") } 68 | 69 | it 'returns the snapshot repository', :with_retries do 70 | expect(JSON.parse(subject.stdout)['backup']). 71 | to include('settings' => a_hash_including( 72 | 'location' => '/var/lib/elasticsearch/backup', 73 | 'max_restore_rate' => '20mb', 74 | 'max_snapshot_rate' => '80mb' 75 | )) 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/helpers/acceptance/tests/usergroup_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'helpers/acceptance/tests/basic_shared_examples' 5 | 6 | shared_examples 'user/group acceptance tests' do 7 | describe 'user/group parameters', first_purge: true, then_purge: true do 8 | describe 'with non-default values', :with_cleanup do 9 | let(:extra_manifest) do 10 | <<-MANIFEST 11 | group { 'esuser': 12 | ensure => 'present', 13 | } -> group { 'esgroup': 14 | ensure => 'present' 15 | } -> user { 'esuser': 16 | ensure => 'present', 17 | groups => ['esgroup', 'esuser'], 18 | before => Class['elasticsearch'], 19 | } 20 | MANIFEST 21 | end 22 | 23 | let(:manifest_class_parameters) do 24 | <<-MANIFEST 25 | elasticsearch_user => 'esuser', 26 | elasticsearch_group => 'esgroup', 27 | MANIFEST 28 | end 29 | 30 | include_examples( 31 | 'basic acceptance tests', 32 | 'es-01' => { 33 | 'config' => { 34 | 'http.port' => 9200, 35 | 'node.name' => 'elasticsearch001' 36 | } 37 | } 38 | ) 39 | 40 | %w[ 41 | /etc/elasticsearch/es-01/elasticsearch.yml 42 | /usr/share/elasticsearch 43 | /var/log/elasticsearch 44 | ].each do |path| 45 | describe file(path) do 46 | it { is_expected.to be_owned_by 'esuser' } 47 | end 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/helpers/class_shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'class' do 4 | it { is_expected.to compile.with_all_deps } 5 | it { is_expected.to contain_augeas('/etc/sysconfig/elasticsearch') } 6 | it { is_expected.to contain_file('/etc/elasticsearch/elasticsearch.yml') } 7 | it { is_expected.to contain_service('elasticsearch') } 8 | end 9 | -------------------------------------------------------------------------------- /spec/matrix.yml: -------------------------------------------------------------------------------- 1 | --- 2 | OS: 3 | - amazonlinux-1-x64 4 | - centos-6-x64 5 | - centos-7-x64 6 | - debian-8-x64 7 | - debian-9-x64 8 | - oracle-6-x64 9 | - oracle-7-x64 10 | - ubuntu-server-1404-x64 11 | - ubuntu-server-1604-x64 12 | PUPPET_VERSION: 13 | - '' 14 | - "~> 6.0" 15 | - "~> 5.0" 16 | - "~> 4.10.0" 17 | TEST_TYPE: 18 | - latest 19 | - 5.6.9 20 | #- snapshot 21 | -------------------------------------------------------------------------------- /spec/setup_acceptance_node.pp: -------------------------------------------------------------------------------- 1 | # Needed for older facter to fetch facts used by the apt module 2 | # 3 | # Might be fixed by: https://github.com/puppetlabs/puppetlabs-apt/pull/1017 4 | if versioncmp(fact('facterversion'), '4.0.0') < 0 and fact('os.name') == 'Ubuntu' { 5 | package { 'lsb-release': 6 | ensure => present, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | # puppetlabs_spec_helper will set up coverage if the env variable is set. 7 | # We want to do this if lib exists and it hasn't been explicitly set. 8 | ENV['COVERAGE'] ||= 'yes' if Dir.exist?(File.expand_path('../lib', __dir__)) 9 | 10 | require 'voxpupuli/test/spec_helper' 11 | 12 | RSpec.configure do |c| 13 | c.facterdb_string_keys = false 14 | c.hiera_config = 'spec/fixtures/hiera.yaml' 15 | end 16 | 17 | add_mocked_facts! 18 | 19 | if File.exist?(File.join(__dir__, 'default_module_facts.yml')) 20 | facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) 21 | facts&.each do |name, value| 22 | add_custom_fact name.to_sym, value 23 | end 24 | end 25 | Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f } 26 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | require 'voxpupuli/acceptance/spec_helper_acceptance' 7 | 8 | configure_beaker(modules: :metadata) 9 | 10 | Dir['./spec/support/acceptance/**/*.rb'].sort.each { |f| require f } 11 | -------------------------------------------------------------------------------- /spec/spec_helper_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet' 4 | -------------------------------------------------------------------------------- /spec/templates/001_elasticsearch.yml.erb_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'yaml' 5 | 6 | class String 7 | def config 8 | "### MANAGED BY PUPPET ###\n---#{unindent}" 9 | end 10 | 11 | def unindent 12 | gsub(%r{^#{scan(%r{^\s*}).min_by(&:length)}}, '') 13 | end 14 | end 15 | 16 | describe 'elasticsearch.yml.erb' do 17 | let :harness do 18 | TemplateHarness.new( 19 | 'templates/etc/elasticsearch/elasticsearch.yml.erb' 20 | ) 21 | end 22 | 23 | it 'renders normal hashes' do 24 | harness.set( 25 | '@data', 26 | 'node.name' => 'test', 27 | 'path.data' => '/mnt/test', 28 | 'discovery.zen.ping.unicast.hosts' => %w[ 29 | host1 host2 30 | ] 31 | ) 32 | 33 | expect(YAML.safe_load(harness.run)).to eq(YAML.safe_load(%( 34 | discovery.zen.ping.unicast.hosts: 35 | - host1 36 | - host2 37 | node.name: test 38 | path.data: /mnt/test 39 | ).config)) 40 | end 41 | 42 | it 'renders arrays of hashes correctly' do 43 | harness.set( 44 | '@data', 45 | 'data' => [ 46 | { 'key' => 'value0', 47 | 'other_key' => 'othervalue0' }, 48 | { 'key' => 'value1', 49 | 'other_key' => 'othervalue1' } 50 | ] 51 | ) 52 | 53 | expect(YAML.safe_load(harness.run)).to eq(YAML.safe_load(%( 54 | data: 55 | - key: value0 56 | other_key: othervalue0 57 | - key: value1 58 | other_key: othervalue1 59 | ).config)) 60 | end 61 | 62 | it 'quotes IPv6 loopback addresses' do 63 | harness.set( 64 | '@data', 65 | 'network.host' => ['::', '[::]'] 66 | ) 67 | 68 | expect(YAML.safe_load(harness.run)).to eq(YAML.safe_load(%( 69 | network.host: 70 | - "::" 71 | - "[::]" 72 | ).config)) 73 | end 74 | 75 | it 'does not quote numeric values' do 76 | harness.set( 77 | '@data', 78 | 'some.setting' => '10' 79 | ) 80 | 81 | expect(YAML.safe_load(harness.run)).to eq(YAML.safe_load(%( 82 | some.setting: 10 83 | ).config)) 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /spec/templates/002_jvm.options.erb_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'jvm.options.epp' do 6 | let :harness do 7 | TemplateHarness.new( 8 | 'templates/etc/elasticsearch/jvm.options.d/jvm.options.epp' 9 | ) 10 | end 11 | 12 | it 'render the same string each time' do 13 | harness.set( 14 | '@_sorted_jvm_options', [ 15 | '-Xms2g', 16 | '-Xmx2g' 17 | ] 18 | ) 19 | 20 | first_render = harness.run 21 | second_render = harness.run 22 | 23 | expect(first_render).to eq(second_render) 24 | end 25 | 26 | it 'test content' do 27 | harness.set( 28 | '@_sorted_jvm_options', [ 29 | '-Xms2g', 30 | '-Xmx2g' 31 | ] 32 | ) 33 | 34 | expect(harness.run).to eq(%( 35 | ### MANAGED BY PUPPET ### 36 | -Xms2g 37 | -Xmx2g 38 | ).config) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/unit/provider/elastic_parsedfile_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib')) 4 | 5 | require 'spec_helper_rspec' 6 | require 'puppet/provider/elastic_parsedfile' 7 | 8 | describe Puppet::Provider::ElasticParsedFile do 9 | subject do 10 | described_class.tap do |o| 11 | o.instance_eval { @metadata = :metadata } 12 | end 13 | end 14 | 15 | it { is_expected.to respond_to :default_target } 16 | it { is_expected.to respond_to :xpack_config } 17 | 18 | context 'when there is no default_target' do 19 | # describe 'default_target' do 20 | # it 'returns a single whitespace' do 21 | # expect(described_class.default_target).to(eq(' ')) 22 | # end 23 | # end 24 | 25 | describe 'xpack_config' do 26 | value = 'somefile' 27 | result = '/etc/elasticsearch/somefile' 28 | 29 | it 'fails when no value is given' do 30 | expect { described_class.xpack_config }.to raise_error(ArgumentError) 31 | end 32 | 33 | it 'defines default_target when given value' do 34 | expect(described_class.xpack_config(value)).to(eq(result)) 35 | expect(described_class.instance_variable_get(:@default_target)).to(eq(result)) 36 | end 37 | end 38 | end 39 | 40 | context 'whene there is a default_target' do 41 | describe 'xpack_config' do 42 | default_target = '/etc/elasticsearch/somefile' 43 | value = 'otherfile' 44 | described_class.instance_variable_set(:@default_target, default_target) 45 | 46 | it 'fails when no value is given' do 47 | expect { described_class.xpack_config }.to raise_error(ArgumentError) 48 | end 49 | 50 | it 'is idempotent' do 51 | expect(described_class.xpack_config('somefile')).to(eq(default_target)) 52 | end 53 | 54 | it 'still returns the previously defined target when a new value is given' do 55 | expect(described_class.xpack_config(value)).to(eq(default_target)) 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /spec/unit/provider/elastic_yaml_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib')) 4 | 5 | require 'spec_helper_rspec' 6 | require 'puppet/provider/elastic_yaml' 7 | 8 | class String 9 | def flattened 10 | split("\n").reject(&:empty?).map(&:strip).join("\n").strip 11 | end 12 | end 13 | 14 | describe Puppet::Provider::ElasticYaml do 15 | subject do 16 | described_class.tap do |o| 17 | o.instance_eval { @metadata = :metadata } 18 | end 19 | end 20 | 21 | let :unsorted_hash do 22 | [{ 23 | name: 'role', 24 | metadata: { 25 | 'zeta' => { 26 | 'zeta' => 5, 27 | 'gamma' => 4, 28 | 'delta' => 3, 29 | 'beta' => 2, 30 | 'alpha' => 1 31 | }, 32 | 'phi' => [{ 33 | 'zeta' => 3, 34 | 'gamma' => 2, 35 | 'alpha' => 1 36 | }], 37 | 'beta' => 'foobaz', 38 | 'gamma' => 1, 39 | 'alpha' => 'foobar' 40 | } 41 | }] 42 | end 43 | 44 | it { is_expected.to respond_to :to_file } 45 | 46 | describe 'to_file' do 47 | it 'returns sorted yaml' do 48 | expect(described_class.to_file(unsorted_hash).flattened).to( 49 | eq(%( 50 | role: 51 | alpha: foobar 52 | beta: foobaz 53 | gamma: 1 54 | phi: 55 | - alpha: 1 56 | gamma: 2 57 | zeta: 3 58 | zeta: 59 | alpha: 1 60 | beta: 2 61 | delta: 3 62 | gamma: 4 63 | zeta: 5 64 | ).flattened) 65 | ) 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_component_template/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_component_template).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foobar1', 9 | ensure: :present, 10 | provider: :ruby, 11 | content: { 12 | 'template' => { 13 | 'mappings' => { 14 | 'properties' => { 15 | 'dummy1' => { 16 | 'type' => 'keyword' 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | end 24 | 25 | let(:json1) do 26 | { 27 | 'component_templates' => [ 28 | { 29 | 'name' => 'foobar1', 30 | 'component_template' => { 31 | 'template' => { 32 | 'mappings' => { 33 | 'properties' => { 34 | 'dummy1' => { 35 | 'type' => 'keyword' 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | ] 43 | } 44 | end 45 | let(:example2) do 46 | { 47 | name: 'foobar2', 48 | ensure: :present, 49 | provider: :ruby, 50 | content: { 51 | 'template' => { 52 | 'mappings' => { 53 | 'properties' => { 54 | 'dummy2' => { 55 | 'type' => 'keyword' 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | end 63 | 64 | let(:json2) do 65 | { 66 | 'component_templates' => [ 67 | { 68 | 'name' => 'foobar2', 69 | 'component_template' => { 70 | 'template' => { 71 | 'mappings' => { 72 | 'properties' => { 73 | 'dummy2' => { 74 | 'type' => 'keyword' 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | ] 82 | } 83 | end 84 | 85 | let(:bare_resource) do 86 | JSON.dump( 87 | {} 88 | ) 89 | end 90 | 91 | let(:resource) { Puppet::Type::Elasticsearch_component_template.new props } 92 | let(:provider) { described_class.new resource } 93 | let(:props) do 94 | { 95 | name: 'foo', 96 | content: {} 97 | } 98 | end 99 | 100 | include_examples 'REST API', 'component_template', '_component_template/foo' 101 | end 102 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_ilm_policy/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_ilm_policy).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foobar1', 9 | ensure: :present, 10 | provider: :ruby, 11 | content: { 12 | 'policy' => { 13 | 'phases' => { 14 | 'cold' => { 15 | 'min_age' => '30d' 16 | } 17 | } 18 | } 19 | } 20 | } 21 | end 22 | 23 | let(:json1) do 24 | { 25 | 'foobar1' => { 26 | 'policy' => { 27 | 'phases' => { 28 | 'cold' => { 29 | 'min_age' => '30d' 30 | } 31 | } 32 | } 33 | } 34 | } 35 | end 36 | let(:example2) do 37 | { 38 | name: 'foobar2', 39 | ensure: :present, 40 | provider: :ruby, 41 | content: { 42 | 'policy' => { 43 | 'phases' => { 44 | 'warm' => { 45 | 'min_age' => '15d' 46 | } 47 | } 48 | } 49 | } 50 | } 51 | end 52 | 53 | let(:json2) do 54 | { 55 | 'foobar2' => { 56 | 'policy' => { 57 | 'phases' => { 58 | 'warm' => { 59 | 'min_age' => '15d' 60 | } 61 | } 62 | } 63 | } 64 | } 65 | end 66 | 67 | let(:bare_resource) do 68 | JSON.dump( 69 | {} 70 | ) 71 | end 72 | 73 | let(:resource) { Puppet::Type::Elasticsearch_ilm_policy.new props } 74 | let(:provider) { described_class.new resource } 75 | let(:props) do 76 | { 77 | name: 'foo', 78 | content: {} 79 | } 80 | end 81 | 82 | include_examples 'REST API', 'ilm/policy', '_ilm/policy/foo' 83 | end 84 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_index_template/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_index_template).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foobar1', 9 | ensure: :present, 10 | provider: :ruby, 11 | content: { 12 | 'index_patterns' => ['foorbar1-*'] 13 | } 14 | } 15 | end 16 | 17 | let(:json1) do 18 | { 19 | 'index_templates' => [ 20 | { 21 | 'name' => 'foobar1', 22 | 'index_template' => { 23 | 'index_patterns' => [ 24 | 'foorbar1-*' 25 | ], 26 | } 27 | } 28 | ] 29 | } 30 | end 31 | let(:example2) do 32 | { 33 | name: 'foobar2', 34 | ensure: :present, 35 | provider: :ruby, 36 | content: { 37 | 'index_patterns' => ['foorbar2-*'], 38 | 'template' => { 39 | 'settings' => { 40 | 'number_of_shards' => 1 41 | } 42 | } 43 | } 44 | } 45 | end 46 | 47 | let(:json2) do 48 | { 49 | 'index_templates' => [ 50 | { 51 | 'name' => 'foobar2', 52 | 'index_template' => { 53 | 'index_patterns' => [ 54 | 'foorbar2-*' 55 | ], 56 | 'template' => { 57 | 'settings' => { 58 | 'number_of_shards' => 1 59 | } 60 | }, 61 | } 62 | } 63 | ] 64 | } 65 | end 66 | 67 | let(:bare_resource) do 68 | JSON.dump( 69 | 'composed_of' => [], 70 | 'index_patterns' => ['fooindex-*'] 71 | ) 72 | end 73 | 74 | let(:resource) { Puppet::Type::Elasticsearch_index_template.new props } 75 | let(:provider) { described_class.new resource } 76 | let(:props) do 77 | { 78 | name: 'foo', 79 | content: { 80 | 'index_patterns' => ['fooindex-*'], 81 | 'composed_of' => [] 82 | } 83 | } 84 | end 85 | 86 | include_examples 'REST API', 'index_template', '_index_template/foo' 87 | end 88 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_license/xpack_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_license).provider(:xpack) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:name) { 'xpack' } 7 | 8 | let(:example1) do 9 | { 10 | name: 'xpack', 11 | ensure: :present, 12 | provider: :xpack, 13 | content: { 14 | 'license' => { 15 | 'status' => 'active', 16 | 'uid' => 'cbff45e7-c553-41f7-ae4f-9205eabd80xx', 17 | 'type' => 'trial', 18 | 'issue_date' => '2018-02-22T23:12:05.550Z', 19 | 'issue_date_in_millis' => 1_519_341_125_550, 20 | 'expiry_date' => '2018-03-24T23:12:05.550Z', 21 | 'expiry_date_in_millis' => 1_521_933_125_550, 22 | 'max_nodes' => 1_000, 23 | 'issued_to' => 'test', 24 | 'issuer' => 'elasticsearch', 25 | 'start_date_in_millis' => 1_513_814_400_000 26 | } 27 | } 28 | } 29 | end 30 | 31 | let(:json1) do 32 | { 33 | 'license' => { 34 | 'status' => 'active', 35 | 'uid' => 'cbff45e7-c553-41f7-ae4f-9205eabd80xx', 36 | 'type' => 'trial', 37 | 'issue_date' => '2018-02-22T23:12:05.550Z', 38 | 'issue_date_in_millis' => '1519341125550', 39 | 'expiry_date' => '2018-03-24T23:12:05.550Z', 40 | 'expiry_date_in_millis' => '1521933125550', 41 | 'max_nodes' => '1000', 42 | 'issued_to' => 'test', 43 | 'issuer' => 'elasticsearch', 44 | 'start_date_in_millis' => '1513814400000' 45 | } 46 | } 47 | end 48 | 49 | let(:resource) { Puppet::Type::Elasticsearch_index.new props } 50 | let(:provider) { described_class.new resource } 51 | let(:props) do 52 | { 53 | name: name, 54 | settings: { 55 | 'index' => { 56 | 'number_of_replicas' => 0 57 | } 58 | } 59 | } 60 | end 61 | 62 | include_examples 'REST API', 'xpack/license', nil, true 63 | end 64 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_pipeline/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_pipeline).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foo', 9 | ensure: :present, 10 | provider: :ruby, 11 | content: { 12 | 'description' => 'Sets the foo field to "bar"', 13 | 'processors' => [{ 14 | 'set' => { 15 | 'field' => 'foo', 16 | 'value' => 'bar' 17 | } 18 | }] 19 | } 20 | } 21 | end 22 | 23 | let(:json1) do 24 | { 25 | 'foo' => { 26 | 'description' => 'Sets the foo field to "bar"', 27 | 'processors' => [{ 28 | 'set' => { 29 | 'field' => 'foo', 30 | 'value' => 'bar' 31 | } 32 | }] 33 | } 34 | } 35 | end 36 | 37 | let(:example2) do 38 | { 39 | name: 'baz', 40 | ensure: :present, 41 | provider: :ruby, 42 | content: { 43 | 'description' => 'A pipeline that never gives you up', 44 | 'processors' => [{ 45 | 'set' => { 46 | 'field' => 'firstname', 47 | 'value' => 'rick' 48 | } 49 | }, { 50 | 'set' => { 51 | 'field' => 'lastname', 52 | 'value' => 'astley' 53 | } 54 | }] 55 | } 56 | } 57 | end 58 | 59 | let(:json2) do 60 | { 61 | 'baz' => { 62 | 'description' => 'A pipeline that never gives you up', 63 | 'processors' => [{ 64 | 'set' => { 65 | 'field' => 'firstname', 66 | 'value' => 'rick' 67 | } 68 | }, { 69 | 'set' => { 70 | 'field' => 'lastname', 71 | 'value' => 'astley' 72 | } 73 | }] 74 | } 75 | } 76 | end 77 | 78 | let(:bare_resource) do 79 | JSON.dump( 80 | 'description' => 'Empty pipeline', 81 | 'processors' => [] 82 | ) 83 | end 84 | 85 | let(:resource) { Puppet::Type::Elasticsearch_pipeline.new props } 86 | let(:provider) { described_class.new resource } 87 | let(:props) do 88 | { 89 | name: 'foo', 90 | content: { 91 | 'description' => 'Empty pipeline', 92 | 'processors' => [] 93 | } 94 | } 95 | end 96 | 97 | include_examples 'REST API', 'ingest/pipeline', '_ingest/pipeline/foo' 98 | end 99 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_plugin/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'shared_examples' 4 | 5 | provider_class = Puppet::Type.type(:elasticsearch_plugin).provider(:elasticsearch_plugin) 6 | 7 | describe provider_class do 8 | let(:resource_name) { 'lmenezes/elasticsearch-kopf' } 9 | let(:resource) do 10 | Puppet::Type.type(:elasticsearch_plugin).new( 11 | name: resource_name, 12 | ensure: :present, 13 | provider: 'elasticsearch_plugin' 14 | ) 15 | end 16 | let(:provider) do 17 | provider = provider_class.new 18 | provider.resource = resource 19 | provider 20 | end 21 | let(:shortname) { provider.plugin_name(resource_name) } 22 | let(:klass) { provider_class } 23 | 24 | include_examples 'plugin provider', '7.0.0' 25 | end 26 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_role/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_role).provider(:ruby) do 6 | describe 'instances' do 7 | it 'has an instance method' do 8 | expect(described_class).to respond_to :instances 9 | end 10 | 11 | context 'with no roles' do 12 | it 'returns no resources' do 13 | expect(described_class.parse("\n")).to eq([]) 14 | end 15 | end 16 | 17 | context 'with one role' do 18 | it 'returns one resource' do 19 | expect(described_class.parse(%( 20 | admin: 21 | cluster: all 22 | indices: 23 | '*': all 24 | ))[0]).to eq( 25 | ensure: :present, 26 | name: 'admin', 27 | privileges: { 28 | 'cluster' => 'all', 29 | 'indices' => { 30 | '*' => 'all' 31 | } 32 | } 33 | ) 34 | end 35 | end 36 | 37 | context 'with multiple roles' do 38 | it 'returns three resources' do 39 | expect(described_class.parse(%( 40 | admin: 41 | cluster: all 42 | indices: 43 | '*': all 44 | user: 45 | indices: 46 | '*': read 47 | power_user: 48 | cluster: monitor 49 | indices: 50 | '*': all 51 | )).length).to eq(3) 52 | end 53 | end 54 | end 55 | 56 | describe 'prefetch' do 57 | it 'has a prefetch method' do 58 | expect(described_class).to respond_to :prefetch 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_role_mapping/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_role_mapping).provider(:ruby) do 6 | describe 'instances' do 7 | it 'has an instance method' do 8 | expect(described_class).to respond_to :instances 9 | end 10 | 11 | context 'with no roles' do 12 | it 'returns no resources' do 13 | expect(described_class.parse("\n")).to eq([]) 14 | end 15 | end 16 | 17 | context 'with one role' do 18 | it 'returns one resource' do 19 | expect(described_class.parse(%( 20 | admin: 21 | - "cn=users,dc=example,dc=com" 22 | ))[0]).to eq( 23 | ensure: :present, 24 | name: 'admin', 25 | mappings: [ 26 | 'cn=users,dc=example,dc=com' 27 | ] 28 | ) 29 | end 30 | end 31 | 32 | context 'with multiple roles' do 33 | it 'returns three resources' do 34 | expect(described_class.parse(%( 35 | admin: 36 | - "cn=users,dc=example,dc=com" 37 | user: 38 | - "cn=users,dc=example,dc=com" 39 | - "cn=admins,dc=example,dc=com" 40 | - "cn=John Doe,cn=other users,dc=example,dc=com" 41 | power_user: 42 | - "cn=admins,dc=example,dc=com" 43 | )).length).to eq(3) 44 | end 45 | end 46 | end 47 | 48 | describe 'prefetch' do 49 | it 'has a prefetch method' do 50 | expect(described_class).to respond_to :prefetch 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_slm_policy/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_slm_policy).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foobar1', 9 | ensure: :present, 10 | provider: :ruby, 11 | content: { 12 | 'name' => '', 13 | 'schedule' => '0 30 1 * * ?', 14 | 'repository' => 'backup', 15 | 'config' => {}, 16 | 'retention' => { 17 | 'expire_after' => '60d', 18 | 'min_count' => 2, 19 | 'max_count' => 10 20 | } 21 | } 22 | } 23 | end 24 | 25 | let(:json1) do 26 | { 27 | 'foobar1' => { 28 | 'policy' => { 29 | 'name' => '', 30 | 'schedule' => '0 30 1 * * ?', 31 | 'repository' => 'backup', 32 | 'config' => {}, 33 | 'retention' => { 34 | 'expire_after' => '60d', 35 | 'min_count' => 2, 36 | 'max_count' => 10 37 | } 38 | } 39 | } 40 | } 41 | end 42 | let(:example2) do 43 | { 44 | name: 'foobar2', 45 | ensure: :present, 46 | provider: :ruby, 47 | content: { 48 | 'name' => '', 49 | 'schedule' => '0 30 1 * * ?', 50 | 'repository' => 'backup', 51 | 'config' => {}, 52 | 'retention' => { 53 | 'expire_after' => '60d', 54 | 'min_count' => 2, 55 | 'max_count' => 10 56 | } 57 | } 58 | } 59 | end 60 | 61 | let(:json2) do 62 | { 63 | 'foobar2' => { 64 | 'policy' => { 65 | 'name' => '', 66 | 'schedule' => '0 30 1 * * ?', 67 | 'repository' => 'backup', 68 | 'config' => {}, 69 | 'retention' => { 70 | 'expire_after' => '60d', 71 | 'min_count' => 2, 72 | 'max_count' => 10 73 | } 74 | } 75 | } 76 | } 77 | end 78 | 79 | let(:bare_resource) do 80 | JSON.dump( 81 | {} 82 | ) 83 | end 84 | 85 | let(:resource) { Puppet::Type::Elasticsearch_slm_policy.new props } 86 | let(:provider) { described_class.new resource } 87 | let(:props) do 88 | { 89 | name: 'foo', 90 | content: {} 91 | } 92 | end 93 | 94 | include_examples 'REST API', 'slm/policy', '_slm/policy/foo' 95 | end 96 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_snapshot_repository/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_snapshot_repository).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foobar1', 9 | ensure: :present, 10 | provider: :ruby, 11 | location: '/bak1', 12 | type: 'fs', 13 | compress: true 14 | } 15 | end 16 | 17 | let(:json1) do 18 | { 19 | 'foobar1' => { 20 | 'type' => 'fs', 21 | 'settings' => { 22 | 'compress' => true, 23 | 'location' => '/bak1' 24 | } 25 | } 26 | } 27 | end 28 | 29 | let(:example2) do 30 | { 31 | name: 'foobar2', 32 | ensure: :present, 33 | provider: :ruby, 34 | location: '/bak2', 35 | type: 'fs', 36 | compress: true 37 | } 38 | end 39 | 40 | let(:json2) do 41 | { 42 | 'foobar2' => { 43 | 'type' => 'fs', 44 | 'settings' => { 45 | 'compress' => true, 46 | 'location' => '/bak2' 47 | } 48 | } 49 | } 50 | end 51 | 52 | let(:bare_resource) do 53 | JSON.dump( 54 | 'type' => 'fs', 55 | 'settings' => { 56 | 'compress' => true, 57 | 'location' => '/backups' 58 | } 59 | ) 60 | end 61 | 62 | let(:resource) { Puppet::Type::Elasticsearch_snapshot_repository.new props } 63 | let(:provider) { described_class.new resource } 64 | let(:props) do 65 | { 66 | name: 'backup', 67 | type: 'fs', 68 | compress: true, 69 | location: '/backups' 70 | } 71 | end 72 | 73 | include_examples 'REST API', 'snapshot', '_snapshot/backup' 74 | end 75 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_template/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../../helpers/unit/provider/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_template).provider(:ruby) do # rubocop:disable RSpec/MultipleMemoizedHelpers 6 | let(:example1) do 7 | { 8 | name: 'foobar1', 9 | ensure: :present, 10 | provider: :ruby, 11 | content: { 12 | 'aliases' => {}, 13 | 'mappings' => {}, 14 | 'settings' => {}, 15 | 'template' => 'foobar1-*', 16 | 'order' => 1 17 | } 18 | } 19 | end 20 | 21 | let(:json1) do 22 | { 23 | 'foobar1' => { 24 | 'aliases' => {}, 25 | 'mappings' => {}, 26 | 'order' => 1, 27 | 'settings' => {}, 28 | 'template' => 'foobar1-*' 29 | } 30 | } 31 | end 32 | 33 | let(:example2) do 34 | { 35 | name: 'foobar2', 36 | ensure: :present, 37 | provider: :ruby, 38 | content: { 39 | 'aliases' => {}, 40 | 'mappings' => {}, 41 | 'settings' => {}, 42 | 'template' => 'foobar2-*', 43 | 'order' => 2 44 | } 45 | } 46 | end 47 | 48 | let(:json2) do 49 | { 50 | 'foobar2' => { 51 | 'aliases' => {}, 52 | 'mappings' => {}, 53 | 'order' => 2, 54 | 'settings' => {}, 55 | 'template' => 'foobar2-*' 56 | } 57 | } 58 | end 59 | 60 | let(:bare_resource) do 61 | JSON.dump( 62 | 'order' => 0, 63 | 'aliases' => {}, 64 | 'mappings' => {}, 65 | 'template' => 'fooindex-*' 66 | ) 67 | end 68 | 69 | let(:resource) { Puppet::Type::Elasticsearch_template.new props } 70 | let(:provider) { described_class.new resource } 71 | let(:props) do 72 | { 73 | name: 'foo', 74 | content: { 75 | 'template' => 'fooindex-*' 76 | } 77 | } 78 | end 79 | 80 | include_examples 'REST API', 'template', '_template/foo' 81 | end 82 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_user/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_user).provider(:ruby) do 6 | describe 'instances' do 7 | it 'has an instance method' do 8 | expect(described_class).to respond_to :instances 9 | end 10 | 11 | context 'without users' do 12 | it 'returns no resources' do 13 | allow(described_class).to receive(:command_with_path).with('list').and_return( 14 | 'No users found' 15 | ) 16 | 17 | expect(described_class.instances.size).to eq(0) 18 | expect(described_class).to have_received(:command_with_path).with('list') 19 | end 20 | end 21 | 22 | context 'with one user' do 23 | it 'returns one resource' do 24 | allow(described_class).to receive(:command_with_path).with('list').and_return( 25 | 'elastic : admin*,power_user' 26 | ) 27 | 28 | expect(described_class.instances[0].instance_variable_get( 29 | '@property_hash' 30 | )).to eq( 31 | ensure: :present, 32 | name: 'elastic', 33 | provider: :ruby 34 | ) 35 | expect(described_class).to have_received(:command_with_path).with('list') 36 | end 37 | end 38 | 39 | context 'with multiple users' do 40 | it 'returns three resources' do 41 | allow(described_class).to receive( 42 | :command_with_path 43 | ).with('list').and_return( 44 | <<-EOL 45 | elastic : admin* 46 | logstash : user 47 | kibana : kibana 48 | EOL 49 | ) 50 | 51 | expect(described_class.instances.length).to eq(3) 52 | 53 | expect(described_class).to have_received( 54 | :command_with_path 55 | ).with('list') 56 | end 57 | end 58 | end 59 | 60 | describe 'prefetch' do 61 | it 'has a prefetch method' do 62 | expect(described_class).to respond_to :prefetch 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_user_file/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_user_file).provider(:ruby) do 6 | describe 'instances' do 7 | it 'has an instance method' do 8 | expect(described_class).to respond_to :instances 9 | end 10 | 11 | context 'without users' do 12 | it 'returns no resources' do 13 | expect(described_class.parse("\n")).to eq([]) 14 | end 15 | end 16 | 17 | context 'with one user' do 18 | it 'returns one resource' do 19 | expect(described_class.parse(%( 20 | elastic:$2a$10$DddrTs0PS3qNknUTq0vpa.g.0JpU.jHDdlKp1xox1W5ZHX.w8Cc8C 21 | ).gsub(%r{^\s+}, ''))[0]).to eq( 22 | name: 'elastic', 23 | hashed_password: '$2a$10$DddrTs0PS3qNknUTq0vpa.g.0JpU.jHDdlKp1xox1W5ZHX.w8Cc8C', 24 | record_type: :ruby 25 | ) 26 | end 27 | end 28 | 29 | context 'with multiple users' do 30 | it 'returns three resources' do 31 | expect(described_class.parse(%( 32 | 33 | admin:$2a$10$DddrTs0PS3qNknUTq0vpa.g.0JpU.jHDdlKp1xox1W5ZHX.w8Cc8C 34 | user:$2a$10$caYr8GhYeJ2Yo0yEhQhQvOjLSwt8Lm6MKQWx8WSnZ/L/IL5sGdQFu 35 | kibana:$2a$10$daYr8GhYeJ2Yo0yEhQhQvOjLSwt8Lm6MKQWx8WSnZ/L/IL5sGdQFu 36 | ).gsub(%r{^\s+}, '')).length).to eq(3) 37 | end 38 | end 39 | end 40 | 41 | describe 'prefetch' do 42 | it 'has a prefetch method' do 43 | expect(described_class).to respond_to :prefetch 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/unit/provider/elasticsearch_user_roles/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_user_roles). 6 | provider(:ruby) do 7 | describe 'instances' do 8 | it 'has an instance method' do 9 | expect(described_class).to respond_to :instances 10 | end 11 | 12 | context 'without roles' do 13 | it 'returns no resources' do 14 | expect(described_class.parse("\n")).to eq([]) 15 | end 16 | end 17 | 18 | context 'with one user' do 19 | it 'returns one resource' do 20 | expect(described_class.parse(%( 21 | admin:elastic 22 | power_user:elastic 23 | ))[0]).to eq( 24 | name: 'elastic', 25 | roles: %w[admin power_user] 26 | ) 27 | end 28 | end 29 | 30 | context 'with multiple users' do 31 | it 'returns three resources' do 32 | expect(described_class.parse(%( 33 | admin:elastic 34 | logstash:user 35 | kibana:kibana 36 | )).length).to eq(3) 37 | end 38 | end 39 | end 40 | 41 | describe 'prefetch' do 42 | it 'has a prefetch method' do 43 | expect(described_class).to respond_to :prefetch 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/unit/puppet_x/elastic/hash_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib')) 4 | 5 | require 'spec_helper_rspec' 6 | require 'puppet_x/elastic/hash' 7 | 8 | describe Puppet_X::Elastic::SortedHash do 9 | subject { { 'foo' => 1, 'bar' => 2 } } 10 | 11 | describe 'each_pair' do 12 | it { is_expected.to respond_to :each_pair } 13 | 14 | it 'yields values' do 15 | expect { |b| subject.each_pair(&b) }.to yield_control.exactly(2).times 16 | end 17 | 18 | it 'returns an Enumerator if not passed a block' do 19 | expect(subject.each_pair).to be_an_instance_of(Enumerator) 20 | end 21 | 22 | it 'returns values' do 23 | subject.each_pair.map { |k, v| [k, v] }.should == subject.to_a 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_ilm_policy_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_ilm_policy) do 6 | let(:resource_name) { 'test_ilm_policy' } 7 | 8 | include_examples 'REST API types', 'ilm_policy', :content 9 | end 10 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_index_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_index) do 6 | let(:resource_name) { 'test-index' } 7 | 8 | include_examples 'REST API types', 'index', :settings 9 | 10 | describe 'settings' do 11 | let(:resource) do 12 | described_class.new( 13 | name: resource_name, 14 | ensure: 'present', 15 | settings: { 16 | 'index' => { 17 | 'number_of_replicas' => '0' 18 | } 19 | } 20 | ) 21 | end 22 | 23 | let(:settings) { resource.property(:settings) } 24 | 25 | describe 'insync?' do 26 | describe 'synced properties' do 27 | let(:is_settings) do 28 | { 29 | 'index' => { 30 | 'creation_date' => 1_487_354_196_301, 31 | 'number_of_replicas' => 0, 32 | 'number_of_shards' => 5, 33 | 'provided_name' => 'a', 34 | 'uuid' => 'vtjrcgyerviqllrakslrsw', 35 | 'version' => { 36 | 'created' => 5_020_199 37 | } 38 | } 39 | } 40 | end 41 | 42 | it 'only enforces defined settings' do 43 | expect(settings).to be_insync(is_settings) 44 | end 45 | end 46 | 47 | describe 'out-of-sync properties' do 48 | let(:is_settings) do 49 | { 50 | 'index' => { 51 | 'creation_date' => 1_487_354_196_301, 52 | 'number_of_replicas' => 1, 53 | 'number_of_shards' => 5, 54 | 'provided_name' => 'a', 55 | 'uuid' => 'vtjrcgyerviqllrakslrsw', 56 | 'version' => { 57 | 'created' => 5_020_199 58 | } 59 | } 60 | } 61 | end 62 | 63 | it 'detects out-of-sync nested values' do 64 | expect(settings).not_to be_insync(is_settings) 65 | end 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_license_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_license) do 6 | let(:resource_name) { 'license' } 7 | 8 | include_examples 'REST API types', 'license', :content 9 | 10 | describe 'license' do 11 | let(:resource) do 12 | described_class.new( 13 | name: resource_name, 14 | ensure: 'present', 15 | content: { 16 | 'license' => { 17 | 'uid' => 'cbff45e7-c553-41f7-ae4f-9205eabd80xx', 18 | 'type' => 'trial', 19 | 'issue_date_in_millis' => '1519341125550', 20 | 'expiry_date_in_millis' => '1521933125550', 21 | 'max_nodes' => '1000', 22 | 'issued_to' => 'test', 23 | 'issuer' => 'elasticsearch', 24 | 'signature' => 'secretvalue', 25 | 'start_date_in_millis' => '1513814400000' 26 | } 27 | } 28 | ) 29 | end 30 | 31 | let(:content) { resource.property(:content) } 32 | 33 | describe 'insync?' do 34 | let(:is_content) do 35 | { 36 | 'license' => { 37 | 'status' => 'active', 38 | 'uid' => 'cbff45e7-c553-41f7-ae4f-9205eabd80xx', 39 | 'type' => 'trial', 40 | 'issue_date' => '2018-02-22T23:12:05.550Z', 41 | 'issue_date_in_millis' => 1_519_341_125_550, 42 | 'expiry_date' => '2018-03-24T23:12:05.550Z', 43 | 'expiry_date_in_millis' => 1_521_933_125_550, 44 | 'max_nodes' => 1_000, 45 | 'issued_to' => 'test', 46 | 'issuer' => 'elasticsearch', 47 | 'start_date_in_millis' => 1_513_814_400_000 48 | } 49 | } 50 | end 51 | 52 | describe 'synced properties' do 53 | it 'only enforces defined content' do 54 | expect(content).to be_insync(is_content) 55 | end 56 | end 57 | 58 | describe 'out-of-sync property' do 59 | { 60 | 'uid' => 'cbff45e7-c553-41f7-ae4f-xxxxxxxxxxxx', 61 | 'issue_date_in_millis' => '1513814400000', 62 | 'expiry_date_in_millis' => '1533167999999', 63 | 'start_date_in_millis' => '-1' 64 | }.each_pair do |field, value| 65 | let(:changed_content) do 66 | is_content['license'][field] = value 67 | is_content 68 | end 69 | 70 | it "detection for #{field}" do 71 | expect(content).not_to be_insync(changed_content) 72 | end 73 | end 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_pipeline_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_pipeline) do 6 | let(:resource_name) { 'test_pipeline' } 7 | 8 | include_examples 'REST API types', 'pipeline', :content 9 | end 10 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_plugin_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_plugin) do 6 | let(:resource_name) { 'lmenezes/elasticsearch-kopf' } 7 | 8 | describe 'input validation' do 9 | describe 'when validating attributes' do 10 | %i[configdir java_opts java_home name source url proxy].each do |param| 11 | it "has a #{param} parameter" do 12 | expect(described_class.attrtype(param)).to eq(:param) 13 | end 14 | end 15 | 16 | it 'has an ensure property' do 17 | expect(described_class.attrtype(:ensure)).to eq(:property) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_role_mapping_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_role_mapping) do 6 | let(:resource_name) { 'elastic_role' } 7 | 8 | describe 'when validating attributes' do 9 | [:name].each do |param| 10 | it "has a #{param} parameter" do 11 | expect(described_class.attrtype(param)).to eq(:param) 12 | end 13 | end 14 | 15 | %i[ensure mappings].each do |prop| 16 | it "has a #{prop} property" do 17 | expect(described_class.attrtype(prop)).to eq(:property) 18 | end 19 | end 20 | end 21 | 22 | describe 'when validating values' do 23 | describe 'ensure' do 24 | it 'supports present as a value for ensure' do 25 | expect do 26 | described_class.new( 27 | name: resource_name, 28 | ensure: :present 29 | ) 30 | end.not_to raise_error 31 | end 32 | 33 | it 'supports absent as a value for ensure' do 34 | expect do 35 | described_class.new( 36 | name: resource_name, 37 | ensure: :absent 38 | ) 39 | end.not_to raise_error 40 | end 41 | 42 | it 'does not support other values' do 43 | expect do 44 | described_class.new( 45 | name: resource_name, 46 | ensure: :foo 47 | ) 48 | end.to raise_error(Puppet::Error, %r{Invalid value}) 49 | end 50 | end 51 | 52 | describe 'name' do 53 | it 'rejects long role names' do 54 | expect do 55 | described_class.new( 56 | name: 'a' * 41 57 | ) 58 | end.to raise_error( 59 | Puppet::ResourceError, 60 | %r{valid values}i 61 | ) 62 | end 63 | 64 | it 'rejects invalid role characters' do 65 | ['@foobar', '0foobar'].each do |role| 66 | expect do 67 | described_class.new( 68 | name: role 69 | ) 70 | end.to raise_error( 71 | Puppet::ResourceError, 72 | %r{valid values}i 73 | ) 74 | end 75 | end 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_role_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_role) do 6 | let(:resource_name) { 'elastic_role' } 7 | 8 | describe 'when validating attributes' do 9 | [:name].each do |param| 10 | it "has a #{param} parameter" do 11 | expect(described_class.attrtype(param)).to eq(:param) 12 | end 13 | end 14 | 15 | %i[ensure privileges].each do |prop| 16 | it "has a #{prop} property" do 17 | expect(described_class.attrtype(prop)).to eq(:property) 18 | end 19 | end 20 | end 21 | 22 | describe 'when validating values' do 23 | describe 'ensure' do 24 | it 'supports present as a value for ensure' do 25 | expect do 26 | described_class.new( 27 | name: resource_name, 28 | ensure: :present 29 | ) 30 | end.not_to raise_error 31 | end 32 | 33 | it 'supports absent as a value for ensure' do 34 | expect do 35 | described_class.new( 36 | name: resource_name, 37 | ensure: :absent 38 | ) 39 | end.not_to raise_error 40 | end 41 | 42 | it 'does not support other values' do 43 | expect do 44 | described_class.new( 45 | name: resource_name, 46 | ensure: :foo 47 | ) 48 | end.to raise_error(Puppet::Error, %r{Invalid value}) 49 | end 50 | end 51 | 52 | describe 'name' do 53 | it 'rejects long role names' do 54 | expect do 55 | described_class.new( 56 | name: 'a' * 41 57 | ) 58 | end.to raise_error( 59 | Puppet::ResourceError, 60 | %r{valid values}i 61 | ) 62 | end 63 | 64 | it 'rejects invalid role characters' do 65 | ['@foobar', '0foobar'].each do |role| 66 | expect do 67 | described_class.new( 68 | name: role 69 | ) 70 | end.to raise_error( 71 | Puppet::ResourceError, 72 | %r{valid values}i 73 | ) 74 | end 75 | end 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_slm_policy_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:elasticsearch_slm_policy) do 6 | let(:resource_name) { 'test_slm_policy' } 7 | 8 | include_examples 'REST API types', 'slm_policy', :content 9 | end 10 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_user_roles_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | describe Puppet::Type.type(:elasticsearch_user_roles) do 6 | let(:resource_name) { 'elastic' } 7 | 8 | describe 'when validating attributes' do 9 | [:name].each do |param| 10 | it "has a #{param} parameter" do 11 | expect(described_class.attrtype(param)).to eq(:param) 12 | end 13 | end 14 | 15 | %i[ensure roles].each do |prop| 16 | it "has a #{prop} property" do 17 | expect(described_class.attrtype(prop)).to eq(:property) 18 | end 19 | end 20 | 21 | describe 'namevar validation' do 22 | it 'has :name as its namevar' do 23 | expect(described_class.key_attributes).to eq([:name]) 24 | end 25 | end 26 | end 27 | 28 | describe 'when validating values' do 29 | describe 'ensure' do 30 | it 'supports present as a value for ensure' do 31 | expect do 32 | described_class.new( 33 | name: resource_name, 34 | ensure: :present 35 | ) 36 | end.not_to raise_error 37 | end 38 | 39 | it 'supports absent as a value for ensure' do 40 | expect do 41 | described_class.new( 42 | name: resource_name, 43 | ensure: :absent 44 | ) 45 | end.not_to raise_error 46 | end 47 | 48 | it 'does not support other values' do 49 | expect do 50 | described_class.new( 51 | name: resource_name, 52 | ensure: :foo 53 | ) 54 | end.to raise_error(Puppet::Error, %r{Invalid value}) 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/unit/type/elasticsearch_user_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_rspec' 4 | 5 | %i[ 6 | elasticsearch_user 7 | elasticsearch_user_file 8 | ].each do |described_type| 9 | describe Puppet::Type.type(described_type) do 10 | let(:resource_name) { 'elastic' } 11 | 12 | describe 'when validating attributes' do 13 | %i[name configdir].each do |param| 14 | it "has a #{param} parameter" do 15 | expect(described_class.attrtype(param)).to eq(:param) 16 | end 17 | end 18 | 19 | [:ensure].each do |prop| 20 | it "has a #{prop} property" do 21 | expect(described_class.attrtype(prop)).to eq(:property) 22 | end 23 | end 24 | 25 | describe 'namevar validation' do 26 | it 'has :name as its namevar' do 27 | expect(described_class.key_attributes).to eq([:name]) 28 | end 29 | end 30 | end 31 | 32 | describe 'when validating values' do 33 | describe 'ensure' do 34 | it 'supports present as a value for ensure' do 35 | expect do 36 | described_class.new( 37 | name: resource_name, 38 | ensure: :present 39 | ) 40 | end.not_to raise_error 41 | end 42 | 43 | it 'supports absent as a value for ensure' do 44 | expect do 45 | described_class.new( 46 | name: resource_name, 47 | ensure: :absent 48 | ) 49 | end.not_to raise_error 50 | end 51 | 52 | it 'does not support other values' do 53 | expect do 54 | described_class.new( 55 | name: resource_name, 56 | ensure: :foo 57 | ) 58 | end.to raise_error(Puppet::Error, %r{Invalid value}) 59 | end 60 | end 61 | 62 | { 63 | hashed_password: :property, 64 | password: :param 65 | }.each_pair do |attribute, type| 66 | next unless described_class.respond_to? attribute 67 | 68 | describe attribute.to_s do 69 | it "has a #{attrtype} #{type}" do 70 | expect(described_class.attrtype(attribute)).to eq(type) 71 | end 72 | end 73 | 74 | next unless attribute == :password 75 | 76 | it 'rejects short passwords' do 77 | expect do 78 | described_class.new( 79 | name: resource_name, 80 | password: 'foo' 81 | ) 82 | end.to raise_error(Puppet::Error, %r{must be at least}) 83 | end 84 | end 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /spec/unit/type/es_instance_conn_validator_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' 4 | 5 | describe Puppet::Type.type(:es_instance_conn_validator) do 6 | let(:resource_name) { 'conn-validator' } 7 | let(:conn_validator) do 8 | Puppet::Type.type(:es_instance_conn_validator). 9 | new(name: resource_name) 10 | end 11 | 12 | describe 'when validating attributes' do 13 | %i[name server port timeout sleep_interval].each do |param| 14 | it "has a #{param} parameter" do 15 | expect(described_class.attrtype(param)).to eq(:param) 16 | end 17 | end 18 | 19 | [:ensure].each do |prop| 20 | it "has a #{prop} property" do 21 | expect(described_class.attrtype(prop)).to eq(:property) 22 | end 23 | end 24 | 25 | describe 'namevar validation' do 26 | it 'has :name as its namevar' do 27 | expect(described_class.key_attributes).to eq([:name]) 28 | end 29 | end 30 | end 31 | 32 | describe 'when validating values' do 33 | describe 'ensure' do 34 | it 'supports present as a value for ensure' do 35 | expect do 36 | described_class.new( 37 | name: resource_name, 38 | ensure: :present 39 | ) 40 | end.not_to raise_error 41 | end 42 | 43 | it 'supports absent as a value for ensure' do 44 | expect do 45 | described_class.new( 46 | name: resource_name, 47 | ensure: :absent 48 | ) 49 | end.not_to raise_error 50 | end 51 | 52 | it 'does not support other values' do 53 | expect do 54 | described_class.new( 55 | name: resource_name, 56 | ensure: :foo 57 | ) 58 | end.to raise_error(Puppet::Error, %r{Invalid value}) 59 | end 60 | end 61 | 62 | describe 'timeout' do 63 | it 'supports a numerical value' do 64 | conn_validator[:timeout] = 120 65 | expect(conn_validator[:timeout]).to eq(120) 66 | end 67 | 68 | it 'has a default value of 60' do 69 | expect(conn_validator[:timeout]).to eq(60) 70 | end 71 | 72 | it 'does not support a non-numeric value' do 73 | expect do 74 | conn_validator[:timeout] = 'string' 75 | end.to raise_error(Puppet::Error, %r{invalid value}) 76 | end 77 | end 78 | 79 | describe 'sleep_interval' do 80 | it 'supports a numerical value' do 81 | conn_validator[:sleep_interval] = 120 82 | expect(conn_validator[:sleep_interval]).to eq(120) 83 | end 84 | 85 | it 'has a default value of 10' do 86 | expect(conn_validator[:sleep_interval]).to eq(10) 87 | end 88 | 89 | it 'does not support a non-numeric value' do 90 | expect do 91 | conn_validator[:sleep_interval] = 'string' 92 | end.to raise_error(Puppet::Error, %r{invalid value}) 93 | end 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /templates/etc/elasticsearch/elasticsearch.yml.erb: -------------------------------------------------------------------------------- 1 | ### MANAGED BY PUPPET ### 2 | <%- 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..","..","lib")) 4 | require 'puppet_x/elastic/deep_to_i' 5 | require 'puppet_x/elastic/hash' 6 | 7 | @yml_string = '' 8 | 9 | if !@data.empty? 10 | 11 | # Sort Hash and transform it into yaml 12 | @yml_string += Puppet_X::Elastic::deep_to_i( 13 | @data 14 | ).extend( 15 | Puppet_X::Elastic::SortedHash 16 | ).to_yaml 17 | end 18 | -%> 19 | <%= @yml_string %> 20 | -------------------------------------------------------------------------------- /templates/etc/elasticsearch/jvm.options.d/jvm.options.epp: -------------------------------------------------------------------------------- 1 | ### MANAGED BY PUPPET ### 2 | <% $sorted_jvm_options.each |$jvm_option| { -%> 3 | <%= $jvm_option %> 4 | <% } -%> 5 | -------------------------------------------------------------------------------- /templates/etc/sysconfig/defaults.erb: -------------------------------------------------------------------------------- 1 | <%- unless scope['elasticsearch::config::init_defaults'].key? 'CONF_FILE' -%> 2 | rm CONF_FILE 3 | <%- end -%> 4 | <% scope['elasticsearch::config::init_defaults'].sort.map do |key, value| -%> 5 | set <%= key %> '<%= value %>' 6 | <% end -%> 7 | -------------------------------------------------------------------------------- /templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb: -------------------------------------------------------------------------------- 1 | d <%= @pid_dir %> 0755 <%= @user %> <%= @group %> - - 2 | -------------------------------------------------------------------------------- /types/multipath.pp: -------------------------------------------------------------------------------- 1 | type Elasticsearch::Multipath = Variant[Array[Stdlib::Absolutepath], Stdlib::Absolutepath] 2 | -------------------------------------------------------------------------------- /types/status.pp: -------------------------------------------------------------------------------- 1 | type Elasticsearch::Status = Enum['enabled', 'disabled', 'running', 'unmanaged'] 2 | --------------------------------------------------------------------------------