├── .editorconfig ├── .fixtures.yml ├── .github ├── 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 ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── files ├── zabbix-server-ipc.te ├── zabbix-server.te └── zapache │ ├── README.md │ ├── httpd-server-status.conf.sample │ ├── userparameter_zapache.conf.sample │ ├── zapache │ ├── zapache-template-active.xml │ └── zapache-template.xml ├── lib └── puppet │ ├── feature │ └── zabbixapi.rb │ ├── provider │ ├── zabbix.rb │ ├── zabbix_host │ │ └── ruby.rb │ ├── zabbix_hostgroup │ │ └── ruby.rb │ ├── zabbix_proxy │ │ └── ruby.rb │ ├── zabbix_template │ │ └── ruby.rb │ └── zabbix_userparameters │ │ └── ruby.rb │ └── type │ ├── zabbix_host.rb │ ├── zabbix_hostgroup.rb │ ├── zabbix_proxy.rb │ ├── zabbix_template.rb │ └── zabbix_userparameters.rb ├── manifests ├── agent.pp ├── database.pp ├── database │ ├── mysql.pp │ ├── postgresql.pp │ └── sqlite.pp ├── init.pp ├── javagateway.pp ├── params.pp ├── proxy.pp ├── repo.pp ├── resources │ ├── agent.pp │ ├── proxy.pp │ ├── template.pp │ ├── userparameters.pp │ └── web.pp ├── sender.pp ├── server.pp ├── startup.pp ├── template.pp ├── userparameter.pp ├── userparameters.pp ├── web.pp ├── zabbixapi.pp └── zapache.pp ├── metadata.json ├── spec ├── acceptance │ ├── agent_spec.rb │ ├── hieradata │ │ ├── common.yaml │ │ └── family │ │ │ └── RedHat │ │ │ ├── 8.yaml │ │ │ └── 9.yaml │ ├── server_spec.rb │ ├── zabbix_host_spec.rb │ ├── zabbix_hostgroup_spec.rb │ ├── zabbix_proxy_spec.rb │ └── zabbix_template_spec.rb ├── classes │ ├── agent_spec.rb │ ├── database_mysql_spec.rb │ ├── database_postgresql_spec.rb │ ├── database_spec.rb │ ├── javagateway_spec.rb │ ├── proxy_spec.rb │ ├── repo_spec.rb │ ├── sender_spec.rb │ ├── server_spec.rb │ ├── userparameter_spec.rb │ └── web_spec.rb ├── defines │ ├── startup_spec.rb │ └── userparameters_spec.rb ├── serverspec_type_zabbixapi.rb ├── setup_acceptance_node.pp ├── spec_helper.rb ├── spec_helper_acceptance.rb ├── support │ └── acceptance │ │ ├── prepare_host.rb │ │ └── supported_versions.rb ├── types │ └── zabbix_host_spec.rb └── unit │ └── puppet │ ├── provider │ ├── zabbix_host │ │ └── ruby.rb │ ├── zabbix_hostgroup │ │ └── ruby.rb │ └── zabbix_proxy │ │ └── ruby.rb │ ├── type │ ├── zabbix_host_spec.rb │ ├── zabbix_hostgroup_spec.rb │ ├── zabbix_proxy_spec.rb │ └── zabbix_template_spec.rb │ └── x │ └── spec_zabbix_types.rb ├── templates ├── api.conf.epp ├── selinux │ └── zabbix-agent.te.erb ├── web │ ├── php-fpm.d.zabbix.conf.epp │ └── zabbix.conf.php.erb ├── zabbix-agent-aix.init.epp ├── zabbix-agent-debian.init.erb ├── zabbix-agent-redhat.init.erb ├── zabbix-agent-systemd.init.erb ├── zabbix-server-debian.init.erb ├── zabbix-server-redhat.init.erb ├── zabbix-server-systemd.init.erb ├── zabbix_agentd.conf.erb ├── zabbix_java_gateway.conf.erb ├── zabbix_proxy.conf.erb └── zabbix_server.conf.erb └── types ├── databases.pp └── historyics.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 | --- 2 | fixtures: 3 | repositories: 4 | apache: https://github.com/puppetlabs/puppetlabs-apache.git 5 | apt: 6 | repo: https://github.com/puppetlabs/puppetlabs-apt.git 7 | tag: v10.0.1 8 | augeas_core: https://github.com/puppetlabs/puppetlabs-augeas_core.git 9 | chocolatey: https://github.com/puppetlabs/puppetlabs-chocolatey.git 10 | concat: https://github.com/puppetlabs/puppetlabs-concat.git 11 | firewall: https://github.com/puppetlabs/puppetlabs-firewall 12 | mysql: https://github.com/puppetlabs/puppetlabs-mysql.git 13 | postgresql: https://github.com/puppetlabs/puppet-postgresql.git 14 | ruby: https://github.com/puppetlabs/puppetlabs-ruby.git 15 | selinux: https://github.com/voxpupuli/puppet-selinux.git 16 | selinux_core: https://github.com/puppetlabs/puppetlabs-selinux_core.git 17 | stdlib: https://github.com/puppetlabs/puppetlabs-stdlib.git 18 | systemd: https://github.com/voxpupuli/puppet-systemd.git 19 | yumrepo_core: https://github.com/puppetlabs/puppetlabs-yumrepo_core.git 20 | -------------------------------------------------------------------------------- /.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 | permissions: 20 | contents: read 21 | 22 | jobs: 23 | puppet: 24 | name: Puppet 25 | uses: voxpupuli/gha-puppet/.github/workflows/beaker.yml@v4 26 | with: 27 | beaker_facter: 'zabbix_version:Zabbix:6.0,7.0' 28 | unit_runs_on: 'cern-self-hosted' 29 | -------------------------------------------------------------------------------- /.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 | permissions: 12 | contents: read 13 | pull-requests: write 14 | 15 | jobs: 16 | labeler: 17 | permissions: 18 | contents: read 19 | pull-requests: write 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/labeler@v5 23 | -------------------------------------------------------------------------------- /.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 | permissions: 15 | contents: write 16 | pull-requests: write 17 | 18 | jobs: 19 | release_prep: 20 | uses: 'voxpupuli/gha-puppet/.github/workflows/prepare_release.yml@v3' 21 | with: 22 | version: ${{ github.event.inputs.version }} 23 | allowed_owner: 'voxpupuli' 24 | secrets: 25 | # Configure secrets here: 26 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 27 | github_pat: '${{ secrets.PCCI_PAT_RELEASE_PREP }}' 28 | -------------------------------------------------------------------------------- /.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 | permissions: 14 | contents: write 15 | 16 | jobs: 17 | release: 18 | name: Release 19 | uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v3 20 | with: 21 | allowed_owner: 'voxpupuli' 22 | secrets: 23 | # Configure secrets here: 24 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 25 | username: ${{ secrets.PUPPET_FORGE_USERNAME }} 26 | api_key: ${{ secrets.PUPPET_FORGE_API_KEY }} 27 | -------------------------------------------------------------------------------- /.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: '10.4.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 | --no-parameter_types-check 6 | -------------------------------------------------------------------------------- /.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 --no-auto-gen-timestamp` 3 | # 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: 3 10 | # Configuration parameters: MaximumRangeSize. 11 | Lint/MissingCopEnableDirective: 12 | Exclude: 13 | - 'spec/acceptance/zabbix_host_spec.rb' 14 | - 'spec/acceptance/zabbix_proxy_spec.rb' 15 | - 'spec/unit/puppet/type/zabbix_host_spec.rb' 16 | 17 | # Offense count: 1 18 | Lint/MissingSuper: 19 | Exclude: 20 | - 'spec/serverspec_type_zabbixapi.rb' 21 | 22 | # Offense count: 1 23 | # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. 24 | # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to 25 | Naming/MethodParameterName: 26 | Exclude: 27 | - 'lib/puppet/provider/zabbix_proxy/ruby.rb' 28 | 29 | # Offense count: 3 30 | # This cop supports unsafe autocorrection (--autocorrect-all). 31 | RSpec/BeEq: 32 | Exclude: 33 | - 'spec/acceptance/zabbix_proxy_spec.rb' 34 | - 'spec/unit/puppet/type/zabbix_template_spec.rb' 35 | 36 | # Offense count: 1 37 | # This cop supports unsafe autocorrection (--autocorrect-all). 38 | RSpec/EmptyExampleGroup: 39 | Exclude: 40 | - 'spec/classes/agent_spec.rb' 41 | 42 | # Offense count: 4 43 | # Configuration parameters: . 44 | # SupportedStyles: have_received, receive 45 | RSpec/MessageSpies: 46 | EnforcedStyle: receive 47 | 48 | # Offense count: 2 49 | RSpec/RepeatedExampleGroupDescription: 50 | Exclude: 51 | - 'spec/defines/startup_spec.rb' 52 | 53 | # Offense count: 4 54 | RSpec/StubbedMock: 55 | Exclude: 56 | - 'spec/unit/puppet/type/zabbix_template_spec.rb' 57 | 58 | # Offense count: 1 59 | Style/MixinUsage: 60 | Exclude: 61 | - 'spec/serverspec_type_zabbixapi.rb' 62 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | Gemfile: 3 | optional: 4 | ':test': 5 | - gem: 'fakefs' 6 | - gem: 'zabbixapi' 7 | spec/spec_helper.rb: 8 | spec_overrides: 9 | - "require 'support/acceptance/supported_versions'" 10 | .puppet-lint.rc: 11 | enabled_lint_checks: 12 | - parameter_documentation 13 | .github/workflows/ci.yml: 14 | with: 15 | beaker_facter: 'zabbix_version:Zabbix:6.0,7.0' 16 | unit_runs_on: 'cern-self-hosted' 17 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Alexander Kostetskiy 2 | Alexander Litvinenko 3 | Andres Villarroel 4 | Bjoern Lippert 5 | Clemens Bergmann 6 | Cory Claflin 7 | Damien Churchill 8 | Davide Ferrari 9 | eander210 10 | Eliran Ben-Zikri 11 | Eric Anderson 12 | Eric Anderson 13 | Ewoud Kohl van Wijngaarden 14 | Felix Kellner 15 | Florian Koch 16 | Florian Koch 17 | Frederic Perrouin 18 | Garhan Attebury 19 | Gene Liverman 20 | Henrik Nicolaisen 21 | hkumarmk 22 | hkumarmk 23 | IceBear 24 | Igor Golubkov 25 | ITler 26 | ju5t 27 | Julien Pivotto 28 | JvdW 29 | karolisc 30 | Luke Blaney 31 | Maciej Stromich 32 | Marc Vanbrabant 33 | Martin Jackson 34 | Martin Merfort 35 | Martin Schütte 36 | Merritt Krakowitzer 37 | Nikita Burtsev 38 | Nikita Stupin 39 | Oyabi 40 | Rafał Zieliński 41 | Rick Lee-Morlang 42 | Robert T 43 | Robert T 44 | Rob Nelson 45 | root 46 | sgnl05 47 | Spencer Krum 48 | Stefan Baryakov 49 | Stefan Baryakov 50 | subkowlex 51 | szemlyanoy 52 | szemlyanoy 53 | Tim Meusel 54 | Tomasz Cholewa 55 | Tom Ford 56 | Vladislav Tkatchev 57 | wdijkerman 58 | Werner Dijkerman 59 | Werner Dijkerman 60 | wilson.prosdocimo 61 | z3rogate 62 | -------------------------------------------------------------------------------- /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', '~> 13.0', :require => false 8 | gem 'puppet_metadata', '~> 5.0', :require => false 9 | gem 'fakefs', :require => false 10 | gem 'zabbixapi', :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', '~> 4.0', :require => false 20 | end 21 | 22 | group :release do 23 | gem 'voxpupuli-release', '~> 5.0', :require => false 24 | end 25 | 26 | gem 'rake', :require => false 27 | 28 | gem 'openvox', ENV.fetch('OPENVOX_GEM_VERSION', [">= 7", "< 9"]), :require => false, :groups => [:test] 29 | 30 | # vim: syntax=ruby 31 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | begin 5 | require 'voxpupuli/test/rake' 6 | rescue LoadError 7 | # only available if gem group test is installed 8 | end 9 | 10 | begin 11 | require 'voxpupuli/acceptance/rake' 12 | rescue LoadError 13 | # only available if gem group acceptance is installed 14 | end 15 | 16 | begin 17 | require 'voxpupuli/release/rake_tasks' 18 | rescue LoadError 19 | # only available if gem group releases is installed 20 | else 21 | GCGConfig.user = 'voxpupuli' 22 | GCGConfig.project = 'puppet-zabbix' 23 | end 24 | 25 | desc "Run main 'test' task and report merged results to coveralls" 26 | task test_with_coveralls: [:test] do 27 | if Dir.exist?(File.expand_path('../lib', __FILE__)) 28 | require 'coveralls/rake/task' 29 | Coveralls::RakeTask.new 30 | Rake::Task['coveralls:push'].invoke 31 | else 32 | puts 'Skipping reporting to coveralls. Module has no lib dir' 33 | end 34 | end 35 | 36 | # vim: syntax=ruby 37 | -------------------------------------------------------------------------------- /files/zabbix-server-ipc.te: -------------------------------------------------------------------------------- 1 | module zabbix-server-ipc 1.0; 2 | 3 | require { 4 | type tmp_t; 5 | type zabbix_t; 6 | class sock_file { create write }; 7 | class unix_stream_socket connectto; 8 | } 9 | 10 | #============= zabbix_t ============== 11 | 12 | allow zabbix_t self:unix_stream_socket connectto; 13 | 14 | allow zabbix_t tmp_t:sock_file { create write }; 15 | -------------------------------------------------------------------------------- /files/zabbix-server.te: -------------------------------------------------------------------------------- 1 | module zabbix-server 1.0; 2 | 3 | require { 4 | type zabbix_t; 5 | class process setrlimit; 6 | } 7 | 8 | #============= zabbix_t ============== 9 | allow zabbix_t self:process setrlimit; 10 | -------------------------------------------------------------------------------- /files/zapache/README.md: -------------------------------------------------------------------------------- 1 | # zapache 1.5 - Apache monitoring script for Zabbix 2 | 3 | The script version 1.4 and template are taken from https://www.zabbix.com/wiki/templates/apache#method_3 4 | 5 | ## What's new 6 | 7 | ### Version 1.5 8 | 9 | * Zapache would cache received apache status page for 60 seconds by default. This eliminates the need to query apache for every item collected. 10 | * Added worker threads graph to a template 11 | * Added new items: status, ping, BusyWorkers, CPULoad 12 | * Added trigger for Apache status to a template 13 | * Ability to specify status page URL as a parameter to the script 14 | * Better error handling 15 | * Added sample conf files for Apache and Zabbix agent 16 | * Added measurement units to a template 17 | * Requires Zabbix version 2.0 and later. 18 | 19 | ## Installation 20 | 21 | ### CentOS 6.4/Zabbix 2.0 from EPEL repo 22 | 23 | #### On the apache server: 24 | 25 | ##### Install files 26 | sudo install -o root -g root -m 0755 zapache /var/lib/zabbixsrv/externalscripts/zapache 27 | sudo install -d /etc/zabbix_agentd.conf.d 28 | echo "Include=/etc/zabbix_agentd.conf.d/" | sudo tee -a /etc/zabbix_agentd.conf 29 | sudo install -o root -g root -m 0644 userparameter_zapache.conf.sample /etc/zabbix_agentd.conf.d/userparameter_zapache.conf 30 | sudo install -o root -g root -m 0644 httpd-server-status.conf.sample /etc/httpd/conf.d/httpd-server-status.conf 31 | ##### Restart 32 | sudo service httpd restart 33 | sudo service zabbix-agent restart 34 | ##### Check if it's working 35 | sudo -u zabbix /var/lib/zabbixsrv/externalscripts/zapache Uptime 36 | sudo -u zabbix zabbix_agentd -p | grep ^zapache 37 | sudo -u zabbix zabbix_get -s localhost -k zapache[Uptime] 38 | 39 | #### On Zabbix server 40 | 41 | Now import zapache-template.xml and zapache-template-active.xml on Zabbix server and bind "Template App Apache Web Server zapache" OR "Template App Apache Web Server zapache Agent Active" template to Apache host. 42 | -------------------------------------------------------------------------------- /files/zapache/httpd-server-status.conf.sample: -------------------------------------------------------------------------------- 1 | # 2 | # This is a sample Apache config file to setup status page. 3 | # Put it in /etc/httpd/conf.d/ or otherwise integrate with Apache conf. 4 | # 5 | 6 | # 7 | # ExtendedStatus controls whether Apache will generate "full" status 8 | # information (ExtendedStatus On) or just basic information (ExtendedStatus 9 | # Off) when the "server-status" handler is called. The default is Off. 10 | # 11 | ExtendedStatus On 12 | 13 | # 14 | # Allow server status reports generated by mod_status, 15 | # with the URL of http://servername/server-status 16 | # Change the ".example.com" to match your domain to enable. 17 | # 18 | 19 | SetHandler server-status 20 | Order deny,allow 21 | Deny from all 22 | Allow from localhost 23 | 24 | -------------------------------------------------------------------------------- /files/zapache/userparameter_zapache.conf.sample: -------------------------------------------------------------------------------- 1 | # 2 | # This is a sample zabbix_agentd config file. 3 | # Put it to /etc/zabbix_agentd.conf.d or otherwise integrate into agent config. 4 | # Edit to your needs. 5 | # 6 | UserParameter=zapache[*],/var/lib/zabbixsrv/externalscripts/zapache \$1 7 | -------------------------------------------------------------------------------- /files/zapache/zapache: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Name: zapache 4 | # 5 | # Checks Apache activity. 6 | # 7 | # Author: Alejandro Michavila 8 | # Modified for Scoreboard Values: Murat Koc, murat@profelis.com.tr 9 | # Modified for using also as external script: Murat Koc, murat@profelis.com.tr 10 | # Modified for outputting usage or ZBX_NOTSUPPORTED: Alejandro Michavila 11 | # Modified to do cacheing for performance, dmitry.frolov@gmail.com 12 | # 13 | # Version: 1.5 14 | # 15 | 16 | zapachever="1.5" 17 | rval=0 18 | value="" 19 | cache_seconds="60" 20 | [ "$TMPDIR" ] || TMPDIR=/tmp 21 | 22 | function usage() 23 | { 24 | echo "zapache version: $zapachever" 25 | echo "usage:" 26 | echo " $0 [] TotalAccesses - Check total accesses." 27 | echo " $0 [] TotalKBytes - Check total KBytes." 28 | echo " $0 [] CPULoad - Check CPU load." 29 | echo " $0 [] Uptime - Check uptime." 30 | echo " $0 [] ReqPerSec - Check requests per second." 31 | echo " $0 [] BytesPerSec - Check Bytes per second." 32 | echo " $0 [] BytesPerReq - Check Bytes per request." 33 | echo " $0 [] BusyWorkers - Check busy workers." 34 | echo " $0 [] IdleWorkers - Check idle workers." 35 | echo " $0 [] version - Version of this script." 36 | echo " $0 [] ping - Check if Apache is up." 37 | echo " $0 [] WaitingForConnection - Check Waiting for Connection processess." 38 | echo " $0 [] StartingUp - Check Starting Up processess." 39 | echo " $0 [] ReadingRequest - Check Reading Request processess." 40 | echo " $0 [] SendingReply - Check Sending Reply processess." 41 | echo " $0 [] KeepAlive - Check KeepAlive Processess." 42 | echo " $0 [] DNSLookup - Check DNSLookup Processess." 43 | echo " $0 [] ClosingConnection - Check Closing Connection Processess." 44 | echo " $0 [] Logging - Check Logging Processess." 45 | echo " $0 [] GracefullyFinishing - Check Gracefully Finishing Processess." 46 | echo " $0 [] IdleCleanupOfWorker - Check Idle Cleanup of Worker Processess." 47 | echo " $0 [] OpenSlotWithNoCurrentProcess - Check Open Slots with No Current Process." 48 | } 49 | 50 | ######## 51 | # Main # 52 | ######## 53 | 54 | if [[ $# == 1 ]];then 55 | #Agent Mode 56 | STATUS_URL="http://`hostname`/server-status?auto" 57 | CASE_VALUE="$1" 58 | elif [[ $# == 2 ]];then 59 | #External Script Mode 60 | STATUS_URL="$1" 61 | case "$STATUS_URL" in 62 | http://*|https://*) ;; 63 | *) STATUS_URL="http://$STATUS_URL/server-status?auto";; 64 | esac 65 | CASE_VALUE="$2" 66 | else 67 | #No Parameter 68 | usage 69 | exit 0 70 | fi 71 | 72 | case "$CASE_VALUE" in 73 | 'version') 74 | echo "$zapachever" 75 | exit 0;; 76 | esac 77 | 78 | cache_prefix="zapache-${STATUS_URL//[^a-zA-Z0-9_-]/_}" 79 | cache="$TMPDIR/$cache_prefix.cache" 80 | cache_timestamp_check="$TMPDIR/$cache_prefix.ts" 81 | # This assumes touch from coreutils 82 | touch -d "@$((`date +%s` - ($cache_seconds - 1)))" "$cache_timestamp_check" 83 | 84 | if [ "$cache" -ot "$cache_timestamp_check" ]; then 85 | curl="`which curl`" 86 | if [ "$curl" ]; then 87 | fetch_url_cmd="$curl --insecure --silent --location" 88 | else 89 | wget="`which wget`" 90 | if [ "$wget" ]; then 91 | fetch_url_cmd="$wget --no-check-certificate --quiet -O -" 92 | else 93 | echo "ZBX_NOTSUPPORTED" 94 | exit 1 95 | fi 96 | fi 97 | 98 | $fetch_url_cmd "$STATUS_URL" > "$cache" 99 | rval=$? 100 | if [ $rval != 0 ]; then 101 | echo "ZBX_NOTSUPPORTED" 102 | exit 1 103 | fi 104 | fi 105 | 106 | case "$CASE_VALUE" in 107 | 'ping') 108 | if [ ! -s "$cache" -o "$cache" -ot "$cache_timestamp_check" ]; then 109 | echo "0" 110 | else 111 | echo "1" 112 | fi 113 | exit 0;; 114 | esac 115 | 116 | if ! [ -s "$cache" ]; then 117 | echo "ZBX_NOTSUPPORTED" 118 | exit 1 119 | fi 120 | 121 | case "$CASE_VALUE" in 122 | 'TotalAccesses') 123 | value="`awk '/^Total Accesses:/ {print $3}' < \"$cache\"`" 124 | rval=$?;; 125 | 'TotalKBytes') 126 | value="`awk '/^Total kBytes:/ {print $3}' < \"$cache\"`" 127 | rval=$?;; 128 | 'CPULoad') 129 | value="`awk '/^CPULoad:/ {print $2}' < \"$cache\"`" 130 | rval=$?;; 131 | 'Uptime') 132 | value="`awk '/^Uptime:/ {print $2}' < \"$cache\"`" 133 | rval=$?;; 134 | 'ReqPerSec') 135 | value="`awk '/^ReqPerSec:/ {print $2}' < \"$cache\"`" 136 | rval=$?;; 137 | 'BytesPerSec') 138 | value="`awk '/^BytesPerSec:/ {print $2}' < \"$cache\"`" 139 | rval=$?;; 140 | 'BytesPerReq') 141 | value="`awk '/^BytesPerReq:/ {print $2}' < \"$cache\"`" 142 | rval=$?;; 143 | 'BusyWorkers') 144 | value="`awk '/^BusyWorkers:/ {print $2}' < \"$cache\"`" 145 | rval=$?;; 146 | 'IdleWorkers') 147 | value="`awk '/^IdleWorkers:/ {print $2}' < \"$cache\"`" 148 | rval=$?;; 149 | 'WaitingForConnection') 150 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "_" }; { print NF-1 }'`" 151 | rval=$?;; 152 | 'StartingUp') 153 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "S" }; { print NF-1 }'`" 154 | rval=$?;; 155 | 'ReadingRequest') 156 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "R" }; { print NF-1 }'`" 157 | rval=$?;; 158 | 'SendingReply') 159 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "W" }; { print NF-1 }'`" 160 | rval=$?;; 161 | 'KeepAlive') 162 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "K" }; { print NF-1 }'`" 163 | rval=$?;; 164 | 'DNSLookup') 165 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "D" }; { print NF-1 }'`" 166 | rval=$?;; 167 | 'ClosingConnection') 168 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "C" }; { print NF-1 }'`" 169 | rval=$?;; 170 | 'Logging') 171 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "L" }; { print NF-1 }'`" 172 | rval=$?;; 173 | 'GracefullyFinishing') 174 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "G" }; { print NF-1 }'`" 175 | rval=$?;; 176 | 'IdleCleanupOfWorker') 177 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "I" }; { print NF-1 }'`" 178 | rval=$?;; 179 | 'OpenSlotWithNoCurrentProcess') 180 | value="`awk '/^Scoreboard:/ {print $2}' < \"$cache\" | awk 'BEGIN { FS = "." }; { print NF-1 }'`" 181 | rval=$?;; 182 | *) 183 | usage 184 | exit 1;; 185 | esac 186 | 187 | if [ "$rval" -eq 0 -a -z "$value" ]; then 188 | rval=1 189 | fi 190 | 191 | if [ "$rval" -ne 0 ]; then 192 | echo "ZBX_NOTSUPPORTED" 193 | fi 194 | 195 | echo "$value" 196 | exit $rval 197 | 198 | # 199 | # end zapache 200 | -------------------------------------------------------------------------------- /lib/puppet/feature/zabbixapi.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/util/feature' 4 | 5 | Puppet.features.add(:zabbixapi, libs: 'zabbixapi') 6 | -------------------------------------------------------------------------------- /lib/puppet/provider/zabbix.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # zabbix provider type for puppet 4 | class Puppet::Provider::Zabbix < Puppet::Provider 5 | # This method is vendored from the AWS SDK, rather than including an 6 | # extra library just to parse an ini file 7 | # Copied from https://github.com/puppetlabs/puppetlabs-aws/blob/2d34b1602bdd564b3f882f683dc000878f539343/lib/puppet_x/puppetlabs/aws.rb#L120 8 | def self.ini_parse(file) 9 | current_section = {} 10 | map = {} 11 | file.rewind 12 | file.each_line do |line| 13 | line = line.split(%r{^|\s;}).first # remove comments 14 | section = line.match(%r{^\s*\[([^\[\]]+)\]\s*$}) unless line.nil? 15 | if section 16 | current_section = section[1] 17 | elsif current_section 18 | item = line.match(%r{^\s*(.+?)\s*=\s*(.+?)\s*$}) unless line.nil? 19 | if item 20 | map[current_section] = map[current_section] || {} 21 | map[current_section][item[1]] = item[2] 22 | end 23 | end 24 | end 25 | map 26 | end 27 | 28 | def ini_parse(file) 29 | self.class.ini_parse(file) 30 | end 31 | 32 | def self.api_config 33 | @api_config ||= ini_parse(File.new('/etc/zabbix/api.conf')) 34 | end 35 | 36 | def api_config 37 | self.class.api_config 38 | end 39 | 40 | def self.zbx 41 | @zbx ||= create_connection 42 | end 43 | 44 | def zbx 45 | self.class.zbx 46 | end 47 | 48 | # Create the api connection 49 | def self.create_connection 50 | protocol = api_config['default']['apache_use_ssl'] == 'true' ? 'https' : 'http' 51 | ZabbixApi.connect( 52 | url: "#{protocol}://#{api_config['default']['zabbix_url']}/api_jsonrpc.php", 53 | user: api_config['default']['zabbix_user'], 54 | password: api_config['default']['zabbix_pass'], 55 | http_user: api_config['default']['zabbix_user'], 56 | http_password: api_config['default']['zabbix_pass'], 57 | ignore_version: true 58 | ) 59 | end 60 | 61 | def create_connection 62 | self.class.create_connection 63 | end 64 | 65 | # Check if host exists. When error raised, return false. 66 | def check_host(host) 67 | zbx.query( 68 | method: 'host.get', 69 | params: { 70 | filter: { 71 | 'host' => [host] 72 | }, 73 | selectParentTemplates: ['host'], 74 | output: ['host'] 75 | } 76 | ) 77 | rescue Puppet::ExecutionFailure 78 | false 79 | end 80 | 81 | # Get the template id from the name. 82 | def get_template_id(zbx, template) 83 | return template if a_number?(template) 84 | 85 | zbx.templates.get_id(host: template) 86 | end 87 | 88 | # Check if given template name exists in current host. 89 | def check_template_in_host(host, template) 90 | template_id = get_template_id(zbx, template) 91 | template_array = zbx.templates.get_ids_by_host(hostids: [zbx.hosts.get_id(host: host)]) 92 | template_array.include?(template_id.to_s) 93 | end 94 | 95 | def transform_to_array_hash(key, value_array) 96 | value_array.map { |a| { key => a } } 97 | end 98 | 99 | # Is it a number? 100 | def a_number?(value) 101 | !value.to_s.match(%r{\A[+-]?\d+?(\.\d+)?\Z}).nil? 102 | end 103 | end 104 | -------------------------------------------------------------------------------- /lib/puppet/provider/zabbix_host/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../zabbix' 4 | Puppet::Type.type(:zabbix_host).provide(:ruby, parent: Puppet::Provider::Zabbix) do 5 | desc 'Puppet provider for managing Zabbix hosts. It uses the Zabbix API to create, read, update and delete hosts.' 6 | confine feature: :zabbixapi 7 | 8 | def self.instances 9 | proxies = zbx.proxies.all 10 | api_hosts = zbx.query( 11 | method: 'host.get', 12 | params: { 13 | selectParentTemplates: ['host'], 14 | selectInterfaces: %w[interfaceid type main ip port useip details], 15 | selectGroups: ['name'], 16 | selectMacros: %w[macro value], 17 | output: %w[host proxy_hostid tls_accept tls_connect tls_issuer tls_subject] 18 | } 19 | ) 20 | 21 | api_hosts.map do |h| 22 | # only select the default interface for given host 23 | # there is only 1 interface that can be default 24 | interface = h['interfaces'].select { |i| i['main'].to_i == 1 }.first 25 | use_ip = !interface['useip'].to_i.zero? 26 | proxy_select = proxies.select { |_name, id| id == h['proxy_hostid'] }.keys.first 27 | proxy_select = '' if proxy_select.nil? 28 | new( 29 | ensure: :present, 30 | id: h['hostid'].to_i, 31 | name: h['host'], 32 | interfaceid: interface['interfaceid'].to_i, 33 | ipaddress: interface['ip'], 34 | use_ip: use_ip, 35 | port: interface['port'].to_i, 36 | groups: h['groups'].map { |g| g['name'] }, 37 | group_create: nil, 38 | templates: h['parentTemplates'].map { |x| x['host'] }, 39 | macros: h['macros'].map { |macro| { macro['macro'] => macro['value'] } }, 40 | proxy: proxy_select, 41 | interfacetype: interface['type'].to_i, 42 | interfacedetails: interface['details'], 43 | tls_accept: h['tls_accept'].to_i, 44 | tls_connect: h['tls_connect'].to_i, 45 | tls_issuer: h['tls_issuer'].to_s, 46 | tls_subject: h['tls_subject'].to_s 47 | ) 48 | end 49 | end 50 | 51 | def self.prefetch(resources) 52 | instances.each do |prov| 53 | if (resource = resources[prov.name]) 54 | resource.provider = prov 55 | end 56 | end 57 | end 58 | 59 | def create 60 | template_ids = get_templateids(@resource[:templates]) 61 | templates = transform_to_array_hash('templateid', template_ids) 62 | 63 | gids = get_groupids(@resource[:groups], @resource[:group_create]) 64 | groups = transform_to_array_hash('groupid', gids) 65 | 66 | proxy_hostid = @resource[:proxy].nil? || @resource[:proxy].empty? ? nil : zbx.proxies.get_id(host: @resource[:proxy]) 67 | 68 | tls_accept = @resource[:tls_accept].nil? ? 1 : @resource[:tls_accept] 69 | tls_connect = @resource[:tls_connect].nil? ? 1 : @resource[:tls_connect] 70 | 71 | # Now we create the host 72 | zbx.hosts.create( 73 | host: @resource[:hostname], 74 | proxy_hostid: proxy_hostid, 75 | interfaces: [ 76 | { 77 | type: @resource[:interfacetype].nil? ? 1 : @resource[:interfacetype], 78 | main: 1, 79 | ip: @resource[:ipaddress].nil? ? '' : @resource[:ipaddress], 80 | dns: @resource[:hostname], 81 | port: @resource[:port], 82 | useip: @resource[:use_ip] ? 1 : 0, 83 | details: @resource[:interfacedetails].nil? ? {} : @resource[:interfacedetails] 84 | } 85 | ], 86 | templates: templates, 87 | groups: groups, 88 | tls_connect: tls_connect, 89 | tls_accept: tls_accept, 90 | tls_issuer: @resource[:tls_issuer].nil? ? '' : @resource[:tls_issuer], 91 | tls_subject: @resource[:tls_subject].nil? ? '' : @resource[:tls_subject] 92 | ) 93 | end 94 | 95 | def exists? 96 | @property_hash[:ensure] == :present 97 | end 98 | 99 | def destroy 100 | zbx.hosts.delete(zbx.hosts.get_id(host: @resource[:hostname])) 101 | end 102 | 103 | # 104 | # Helper methods 105 | # 106 | def get_groupids(group_array, create) 107 | groupids = [] 108 | group_array.each do |g| 109 | id = zbx.hostgroups.get_id(name: g) 110 | if id.nil? 111 | raise Puppet::Error, "The hostgroup (#{g}) does not exist in zabbix. Please use the correct one or set group_create => true." unless create 112 | 113 | groupids << zbx.hostgroups.create(name: g) 114 | else 115 | groupids << id 116 | end 117 | end 118 | groupids 119 | end 120 | 121 | def get_templateids(template_array) 122 | templateids = [] 123 | template_array.each do |t| 124 | template_id = zbx.templates.get_id(host: t) 125 | raise Puppet::Error, "The template #{t} does not exist in Zabbix. Please use a correct one." if template_id.nil? 126 | 127 | templateids << template_id 128 | end 129 | templateids 130 | end 131 | 132 | # 133 | # zabbix_host properties 134 | # 135 | mk_resource_methods 136 | 137 | def ipaddress=(string) 138 | zbx.query( 139 | method: 'hostinterface.update', 140 | params: { 141 | interfaceid: @property_hash[:interfaceid], 142 | ip: string 143 | } 144 | ) 145 | end 146 | 147 | def use_ip=(boolean) 148 | zbx.query( 149 | method: 'hostinterface.update', 150 | params: { 151 | interfaceid: @property_hash[:interfaceid], 152 | useip: boolean ? 1 : 0, 153 | dns: @resource[:hostname] 154 | } 155 | ) 156 | end 157 | 158 | def port=(int) 159 | zbx.query( 160 | method: 'hostinterface.update', 161 | params: { 162 | interfaceid: @property_hash[:interfaceid], 163 | port: int 164 | } 165 | ) 166 | end 167 | 168 | def interfacetype=(int) 169 | zbx.query( 170 | method: 'hostinterface.update', 171 | params: { 172 | interfaceid: @property_hash[:interfaceid], 173 | type: int 174 | } 175 | ) 176 | end 177 | 178 | def interfacedetails=(hash) 179 | zbx.query( 180 | method: 'hostinterface.update', 181 | params: { 182 | interfaceid: @property_hash[:interfaceid], 183 | details: hash 184 | } 185 | ) 186 | end 187 | 188 | def groups=(hostgroups) 189 | gids = get_groupids(hostgroups, @resource[:group_create]) 190 | groups = transform_to_array_hash('groupid', gids) 191 | 192 | zbx.hosts.create_or_update( 193 | host: @resource[:hostname], 194 | groups: groups 195 | ) 196 | end 197 | 198 | def templates=(array) 199 | should_template_ids = get_templateids(array) 200 | 201 | # Get templates we have to clear. Unlinking only isn't really helpful. 202 | is_template_ids = zbx.query( 203 | method: 'host.get', 204 | params: { 205 | hostids: @property_hash[:id], 206 | selectParentTemplates: ['templateid'], 207 | output: ['host'] 208 | } 209 | ).first['parentTemplates'].map { |t| t['templateid'].to_i } 210 | templates_clear = is_template_ids - should_template_ids 211 | 212 | zbx.query( 213 | method: 'host.update', 214 | params: { 215 | hostid: @property_hash[:id], 216 | templates: transform_to_array_hash('templateid', should_template_ids), 217 | templates_clear: transform_to_array_hash('templateid', templates_clear) 218 | } 219 | ) 220 | end 221 | 222 | def macros=(array) 223 | macroarray = array.map { |macro| { 'macro' => macro.first[0], 'value' => macro.first[1] } } 224 | zbx.query( 225 | method: 'host.update', 226 | params: { 227 | hostid: @property_hash[:id], 228 | macros: macroarray 229 | } 230 | ) 231 | end 232 | 233 | def proxy=(string) 234 | zbx.hosts.create_or_update( 235 | host: @resource[:hostname], 236 | proxy_hostid: zbx.proxies.get_id(host: string) 237 | ) 238 | end 239 | 240 | def tls_connect=(int) 241 | @property_hash[:tls_connect] = int 242 | zbx.hosts.create_or_update( 243 | host: @resource[:hostname], 244 | tls_connect: @property_hash[:tls_connect].nil? ? 1 : @property_hash[:tls_connect] 245 | ) 246 | end 247 | 248 | def tls_accept=(int) 249 | @property_hash[:tls_accept] = int 250 | 251 | zbx.hosts.create_or_update( 252 | host: @resource[:hostname], 253 | tls_accept: @property_hash[:tls_accept].nil? ? 1 : @property_hash[:tls_accept] 254 | ) 255 | end 256 | 257 | def tls_issuer=(string) 258 | @property_hash[:tls_issuer] = string 259 | zbx.hosts.create_or_update( 260 | host: @resource[:hostname], 261 | tls_issuer: @property_hash[:tls_issuer].nil? ? '' : @property_hash[:tls_issuer] 262 | ) 263 | end 264 | 265 | def tls_subject=(string) 266 | @property_hash[:tls_subject] = string 267 | zbx.hosts.create_or_update( 268 | host: @resource[:hostname], 269 | tls_subject: @property_hash[:tls_subject].nil? ? '' : @property_hash[:tls_subject] 270 | ) 271 | end 272 | end 273 | -------------------------------------------------------------------------------- /lib/puppet/provider/zabbix_hostgroup/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../zabbix' 4 | Puppet::Type.type(:zabbix_hostgroup).provide(:ruby, parent: Puppet::Provider::Zabbix) do 5 | desc 'Puppet provider for managing Zabbix hostgroups. It defines methods to create, check if exists, and destroy Zabbix hostgroups using the Zabbix API.' 6 | confine feature: :zabbixapi 7 | 8 | def self.instances 9 | api_hostgroups = zbx.hostgroups.all 10 | api_hostgroups.map do |group_name, _id| 11 | new( 12 | ensure: :present, 13 | name: group_name 14 | ) 15 | end 16 | end 17 | 18 | def self.prefetch(resources) 19 | instances.each do |prov| 20 | if (resource = resources[prov.name]) 21 | resource.provider = prov 22 | end 23 | end 24 | end 25 | 26 | def create 27 | # Connect to zabbix api 28 | zbx.hostgroups.create(name: @resource[:name]) 29 | end 30 | 31 | def exists? 32 | @property_hash[:ensure] == :present 33 | end 34 | 35 | def destroy 36 | zbx.hostgroups.delete(zbx.hostgroups.get_id(name: @resource[:name])) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/puppet/provider/zabbix_proxy/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../zabbix' 4 | Puppet::Type.type(:zabbix_proxy).provide(:ruby, parent: Puppet::Provider::Zabbix) do 5 | desc 'Puppet provider for managing Zabbix proxies. It uses the Zabbix API to create, read, update and delete hosts, as well as changing them between active and passive modes.' 6 | confine feature: :zabbixapi 7 | 8 | def initialize(value = {}) 9 | super(value) 10 | @property_flush = {} 11 | end 12 | 13 | mk_resource_methods 14 | 15 | def self.instances 16 | proxies.map do |p| 17 | new(proxy_properties_hash(p)) 18 | end 19 | end 20 | 21 | def self.prefetch(resources) 22 | instances.each do |prov| 23 | if (resource = resources[prov.name]) 24 | resource.provider = prov 25 | end 26 | end 27 | end 28 | 29 | def self.proxies(proxyids = nil) 30 | zbx.query( 31 | method: 'proxy.get', 32 | params: { 33 | proxyids: proxyids, 34 | output: 'extend', 35 | selectInterface: %w[interfaceid type main ip port useip] 36 | }.compact 37 | ) 38 | end 39 | 40 | # Convert from proxy hash returned by API into a resource properties hash 41 | def self.proxy_properties_hash(p) 42 | { 43 | ensure: :present, 44 | # Proxy object properties 45 | proxyid: p['proxyid'].to_i, 46 | name: p['host'], 47 | mode: status_to_mode(p['status']), 48 | # Proxy Interface object properties 49 | interfaceid: p['interface'].is_a?(Hash) ? p['interface']['interfaceid'] : nil, 50 | ipaddress: p['interface'].is_a?(Hash) ? p['interface']['ip'] : nil, 51 | use_ip: if p['interface'].is_a?(Hash) then p['interface']['useip'] == '1' ? :true : :false end, 52 | port: p['interface'].is_a?(Hash) ? p['interface']['port'].to_i : nil 53 | } 54 | end 55 | 56 | def create 57 | mode = @resource[:mode] || :active 58 | 59 | if mode == :passive 60 | useip = if @resource[:use_ip].nil? 61 | 1 62 | else 63 | @resource[:use_ip] == :true ? 1 : 0 64 | end 65 | interface = { 66 | ip: @resource[:ipaddress] || '127.0.0.1', 67 | dns: @resource[:hostname], 68 | useip: useip, 69 | port: @resource[:port] || 10_051 70 | } 71 | else 72 | interface = nil 73 | end 74 | 75 | zbx.proxies.create( 76 | { 77 | host: @resource[:hostname], 78 | status: self.class.mode_to_status(mode), 79 | interface: interface 80 | }.compact 81 | ) 82 | @property_flush[:created] = true 83 | end 84 | 85 | def exists? 86 | @property_hash[:ensure] == :present 87 | end 88 | 89 | def destroy 90 | zbx.proxies.delete([zbx.proxies.get_id(host: @resource[:hostname])].flatten) 91 | @property_flush[:destroyed] = true 92 | end 93 | 94 | def flush 95 | update unless @property_flush[:created] || @property_flush[:destroyed] 96 | 97 | # Update @property_hash so that the output of puppet resource is correct 98 | if @property_flush[:destroyed] 99 | @property_hash.clear 100 | @property_hash[:ensure] = :absent 101 | else 102 | proxy = self.class.proxies(@property_hash[:proxyid]).find { |p| p['host'] == @resource[:hostname] } 103 | @property_hash = self.class.proxy_properties_hash(proxy) 104 | end 105 | end 106 | 107 | def mode=(value) 108 | @property_flush[:mode] = value 109 | end 110 | 111 | def change_to_passive_proxy 112 | Puppet.debug("We're changing to a passive proxy") 113 | # We need to call zbx.proxies.update with an `interface` hash. 114 | 115 | useip = if @resource[:use_ip].nil? 116 | 1 # Default to true 117 | else 118 | @resource[:use_ip] == :true ? 1 : 0 119 | end 120 | 121 | interface = { 122 | ip: @resource[:ipaddress] || @property_hash[:ipaddress] || '127.0.0.1', 123 | dns: @resource[:hostname], # This is the namevar and will always exist 124 | useip: useip, 125 | port: @resource[:port] || @property_hash[:port] || 10_051 126 | } 127 | 128 | zbx.proxies.update( 129 | { 130 | proxyid: @property_hash[:proxyid], 131 | status: self.class.mode_to_status(:passive), 132 | interface: interface 133 | }, 134 | true 135 | ) 136 | end 137 | 138 | def change_to_active_proxy 139 | Puppet.debug("We're changing to an active proxy") 140 | zbx.proxies.update( 141 | { 142 | proxyid: @property_hash[:proxyid], 143 | status: self.class.mode_to_status(:active) 144 | }, 145 | true 146 | ) 147 | end 148 | 149 | def update_interface_properties 150 | useip = if @resource[:use_ip].nil? 151 | nil # Don't provide a default. Keep use_ip unmanaged. 152 | else 153 | @resource[:use_ip] == :true ? 1 : 0 154 | end 155 | 156 | interface = { 157 | interfaceid: @property_hash[:interfaceid], 158 | ip: @resource[:ipaddress], 159 | useip: useip, 160 | port: @resource[:port] 161 | }.compact 162 | 163 | zbx.proxies.update( 164 | { 165 | proxyid: @property_hash[:proxyid], 166 | interface: interface 167 | }, 168 | true 169 | ) 170 | end 171 | 172 | def update 173 | if @property_flush[:mode] == :passive 174 | change_to_passive_proxy 175 | return 176 | end 177 | 178 | if @property_flush[:mode] == :active 179 | change_to_active_proxy 180 | return 181 | end 182 | 183 | # At present, the only properties other than mode that can be updated are the interface properties applicable to passive proxies only. 184 | raise Puppet::Error, "Can't update proxy interface properties for an active proxy" unless @property_hash[:mode] == :passive 185 | 186 | update_interface_properties 187 | end 188 | 189 | def self.status_to_mode(status) 190 | case status.to_i 191 | when 5 192 | :active 193 | when 6 194 | :passive 195 | else 196 | raise Puppet::Error, 'zabbix API returned invalid value for `status`' 197 | end 198 | end 199 | 200 | def self.mode_to_status(mode) 201 | return 5 if mode == :active 202 | 203 | 6 204 | end 205 | end 206 | -------------------------------------------------------------------------------- /lib/puppet/provider/zabbix_template/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../zabbix' 4 | Puppet::Type.type(:zabbix_template).provide(:ruby, parent: Puppet::Provider::Zabbix) do 5 | desc 'Puppet provider that manages Zabbix templates by importing and exporting them in XML format, and creating, updating, or deleting various Zabbix configuration objects. It includes conditional logic based on the Zabbix version being used.' 6 | confine feature: :zabbixapi 7 | 8 | def create 9 | zbx.configurations.import( 10 | format: 'xml', 11 | rules: { 12 | # application parameter was removed on Zabbix 5.4 13 | (@resource[:zabbix_version] =~ %r{[45]\.[02]} ? :applications : nil) => { 14 | deleteMissing: (@resource[:delete_missing_applications].nil? ? false : @resource[:delete_missing_applications]), 15 | createMissing: true 16 | }, 17 | discoveryRules: { 18 | createMissing: true, 19 | deleteMissing: (@resource[:delete_missing_drules].nil? ? false : @resource[:delete_missing_drules]), 20 | updateExisting: true 21 | }, 22 | graphs: { 23 | createMissing: true, 24 | deleteMissing: (@resource[:delete_missing_graphs].nil? ? false : @resource[:delete_missing_graphs]), 25 | updateExisting: true 26 | }, 27 | groups: { 28 | createMissing: true 29 | }, 30 | httptests: { 31 | createMissing: true, 32 | deleteMissing: (@resource[:delete_missing_httptests].nil? ? false : @resource[:delete_missing_httptests]), 33 | updateExisting: true 34 | }, 35 | images: { 36 | createMissing: true, 37 | updateExisting: true 38 | }, 39 | items: { 40 | createMissing: true, 41 | deleteMissing: (@resource[:delete_missing_items].nil? ? false : @resource[:delete_missing_items]), 42 | updateExisting: true 43 | }, 44 | maps: { 45 | createMissing: true, 46 | updateExisting: true 47 | }, 48 | # screens parameter was removed on Zabbix 5.4 49 | (@resource[:zabbix_version] =~ %r{[45]\.[02]} ? :screens : nil) => { 50 | createMissing: true, 51 | updateExisting: true 52 | }, 53 | templateLinkage: { 54 | createMissing: true 55 | }, 56 | templates: { 57 | createMissing: true, 58 | updateExisting: true 59 | }, 60 | # templateDashboards was renamed to templateScreen on Zabbix >= 5.2 61 | (@resource[:zabbix_version] =~ %r{5\.[24]|6\.0} ? :templateDashboards : :templateScreens) => { 62 | createMissing: true, 63 | deleteMissing: (@resource[:delete_missing_templatescreens].nil? ? false : @resource[:delete_missing_templatescreens]), 64 | updateExisting: true 65 | }, 66 | triggers: { 67 | createMissing: true, 68 | deleteMissing: (@resource[:delete_missing_triggers].nil? ? false : @resource[:delete_missing_triggers]), 69 | updateExisting: true 70 | }, 71 | valueMaps: { 72 | createMissing: true 73 | } 74 | }.delete_if { |key, _| key.nil? }, 75 | source: template_contents 76 | ) 77 | end 78 | 79 | def destroy 80 | id = zbx.templates.get_id(host: @resource[:template_name]) 81 | zbx.templates.delete(id) 82 | end 83 | 84 | def exists? 85 | zbx.templates.get_id(host: @resource[:template_name]) 86 | end 87 | 88 | def xml 89 | zbx.configurations.export( 90 | format: 'xml', 91 | options: { 92 | templates: [zbx.templates.get_id(host: @resource[:template_name])] 93 | } 94 | ) 95 | end 96 | 97 | def template_contents 98 | file = File.new(@resource[:template_source], 'rb') 99 | file.read 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /lib/puppet/provider/zabbix_userparameters/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../zabbix' 4 | Puppet::Type.type(:zabbix_userparameters).provide(:ruby, parent: Puppet::Provider::Zabbix) do 5 | desc 'Puppet provider that manages Zabbix user parameters. It allows users to define custom monitoring parameters in Zabbix, and provides methods for creating and checking the existence of a user parameter. It also has a placeholder method for destroying the user parameter.' 6 | confine feature: :zabbixapi 7 | 8 | def create 9 | host = @resource[:hostname] 10 | template = @resource[:template] 11 | 12 | # Find the template_id we are looking for and add it to the host 13 | template_id = get_template_id(zbx, template) 14 | zbx.templates.mass_add( 15 | hosts_id: [zbx.hosts.get_id(host: host)], 16 | templates_id: [template_id] 17 | ) 18 | end 19 | 20 | def exists? 21 | host = @resource[:hostname] 22 | template = @resource[:template] 23 | check_template_in_host(host, template) 24 | end 25 | 26 | def destroy 27 | # TODO: Implement?! 28 | true 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/puppet/type/zabbix_host.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:zabbix_host) do 4 | @doc = 'Manage zabbix hosts' 5 | 6 | ensurable do 7 | desc 'The basic property that the resource should be in.' 8 | defaultvalues 9 | defaultto :present 10 | end 11 | 12 | def munge_boolean(value) 13 | case value 14 | when true, 'true', :true 15 | true 16 | when false, 'false', :false 17 | false 18 | else 19 | raise(Puppet::Error, 'munge_boolean only takes booleans') 20 | end 21 | end 22 | 23 | def munge_encryption(value) 24 | case value 25 | when 1, 'unencrypted', :unencrypted 26 | 1 27 | when 2, 'psk', :psk 28 | 2 29 | when 4, 'cert', :cert 30 | 4 31 | else 32 | raise(Puppet::Error, 'munge_encryption only takes unencrypted, psk or cert') 33 | end 34 | end 35 | 36 | newparam(:hostname, namevar: true) do 37 | desc 'FQDN of the machine.' 38 | end 39 | 40 | newproperty(:id) do 41 | desc 'Internally used hostid' 42 | 43 | validate do |_value| 44 | raise(Puppet::Error, 'id is read-only and is only available via puppet resource.') 45 | end 46 | end 47 | 48 | newproperty(:interfaceid) do 49 | desc 'Internally used identifier for the host interface' 50 | 51 | validate do |_value| 52 | raise(Puppet::Error, 'interfaceid is read-only and is only available via puppet resource.') 53 | end 54 | end 55 | 56 | newproperty(:ipaddress) do 57 | desc 'The IP address of the machine running zabbix agent.' 58 | end 59 | 60 | newproperty(:interfacetype, int: 1) do 61 | desc 'Interface type. 1 for zabbix agent.' 62 | end 63 | 64 | newproperty(:interfacedetails) do 65 | desc 'Additional interface details.' 66 | 67 | def insync?(is) 68 | is.to_s == should.to_s 69 | end 70 | end 71 | 72 | newproperty(:use_ip, boolean: true) do 73 | desc 'Using ipadress instead of dns to connect.' 74 | 75 | newvalues(true, false) 76 | 77 | munge do |value| 78 | @resource.munge_boolean(value) 79 | end 80 | end 81 | 82 | newproperty(:port) do 83 | desc 'The port that the zabbix agent is listening on.' 84 | def insync?(is) 85 | is.to_i == should.to_i 86 | end 87 | end 88 | 89 | newproperty(:groups, array_matching: :all) do 90 | desc 'An array of groups the host belongs to.' 91 | def insync?(is) 92 | is.sort == should.sort 93 | end 94 | end 95 | 96 | newparam(:group_create, boolean: true) do 97 | desc 'Create hostgroup if missing.' 98 | 99 | newvalues(true, false) 100 | 101 | munge do |value| 102 | @resource.munge_boolean(value) 103 | end 104 | end 105 | 106 | newproperty(:templates, array_matching: :all) do 107 | desc 'List of templates which should be loaded for this host.' 108 | def insync?(is) 109 | is.sort == should.sort 110 | end 111 | end 112 | 113 | newproperty(:macros, array_matching: :all) do 114 | desc 'Array of hashes (macros) which should be loaded for this host.' 115 | def insync?(is) 116 | is.sort_by(&:first) == should.sort_by(&:first) 117 | end 118 | end 119 | 120 | newproperty(:proxy) do 121 | desc 'Whether it is monitored by an proxy or not.' 122 | end 123 | 124 | newproperty(:tls_connect) do 125 | desc 'How the server connect to the client (unencrypted, psk or cert)' 126 | def insync?(is) 127 | is.to_i == should.to_i 128 | end 129 | 130 | munge do |value| 131 | @resource.munge_encryption(value) 132 | end 133 | end 134 | 135 | newproperty(:tls_accept) do 136 | desc 'How the client connect to the server (unencrypted, psk or cert)' 137 | def insync?(is) 138 | is.to_i == should.to_i 139 | end 140 | 141 | munge do |value| 142 | @resource.munge_encryption(value) 143 | end 144 | end 145 | 146 | newproperty(:tls_issuer) do 147 | desc 'Certificate issuer.' 148 | end 149 | 150 | newproperty(:tls_subject) do 151 | desc 'Certificate subject.' 152 | end 153 | 154 | autorequire(:file) { '/etc/zabbix/api.conf' } 155 | end 156 | -------------------------------------------------------------------------------- /lib/puppet/type/zabbix_hostgroup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:zabbix_hostgroup) do 4 | @doc = 'Manage zabbix hostgroups' 5 | 6 | ensurable do 7 | desc 'The basic property that the resource should be in.' 8 | defaultvalues 9 | defaultto :present 10 | end 11 | 12 | newparam(:name, namevar: true) do 13 | desc 'hostgroup name' 14 | end 15 | 16 | autorequire(:file) { '/etc/zabbix/api.conf' } 17 | end 18 | -------------------------------------------------------------------------------- /lib/puppet/type/zabbix_proxy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:zabbix_proxy) do 4 | @doc = 'Manage zabbix proxies' 5 | 6 | ensurable do 7 | desc 'The basic property that the resource should be in.' 8 | defaultvalues 9 | defaultto :present 10 | end 11 | 12 | def munge_boolean_to_symbol(value) 13 | # insync? doesn't work with actual booleans 14 | # see https://tickets.puppetlabs.com/browse/PUP-2368 15 | value = value.downcase if value.respond_to? :downcase 16 | 17 | case value 18 | when true, :true, 'true', :yes, 'yes' 19 | :true 20 | when false, :false, 'false', :no, 'no' 21 | :false 22 | else 23 | raise ArgumentError, 'expected a boolean value' 24 | end 25 | end 26 | 27 | # Standard properties 28 | newparam(:hostname, namevar: true) do 29 | desc 'FQDN of the proxy.' 30 | end 31 | 32 | newproperty(:mode) do 33 | desc 'The kind of mode the proxy running. Active (0) or passive (1).' 34 | 35 | newvalues(:active, :passive, 0, 1, '0', '1') 36 | 37 | munge do |value| 38 | case value 39 | when 0, '0' 40 | :active 41 | when 1, '1' 42 | :passive 43 | else 44 | super(value) 45 | end 46 | end 47 | end 48 | 49 | newproperty(:proxyid) do 50 | desc '(readonly) ID of the proxy' 51 | validate { |_val| raise Puppet::Error, 'proxyid is read-only' } 52 | end 53 | 54 | # Interface properties (applicable to passive proxies) 55 | newproperty(:ipaddress) do 56 | desc 'The IP address of the machine running zabbix proxy.' 57 | 58 | validate do |value| 59 | require 'ipaddr' 60 | 61 | begin 62 | IPAddr.new(value) 63 | rescue StandardError => e 64 | raise Puppet::Error, e.to_s 65 | end 66 | end 67 | end 68 | 69 | newproperty(:use_ip) do 70 | desc 'Using ipadress instead of dns to connect. Is used by the zabbix-api command.' 71 | 72 | munge { |value| @resource.munge_boolean_to_symbol(value) } 73 | end 74 | 75 | newproperty(:port) do 76 | desc 'The port that the zabbix proxy is listening on.' 77 | 78 | validate do |value| 79 | if value.is_a?(String) 80 | raise Puppet::Error, 'invalid port' unless value =~ %r{^\d+$} 81 | raise Puppet::Error, 'invalid port' unless value.to_i.between?(1, 65_535) 82 | 83 | return 84 | end 85 | if value.is_a?(Integer) 86 | raise Puppet::Error, 'invalid port' unless value.between?(1, 65_535) 87 | 88 | return 89 | end 90 | raise Puppet::Error, 'invalid port' 91 | end 92 | 93 | munge(&:to_i) 94 | end 95 | 96 | newproperty(:interfaceid) do 97 | desc '(readonly) ID of the interface' 98 | validate { |_val| raise Puppet::Error, 'interfaceid is read-only' } 99 | end 100 | 101 | autorequire(:file) { '/etc/zabbix/api.conf' } 102 | end 103 | -------------------------------------------------------------------------------- /lib/puppet/type/zabbix_template.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:zabbix_template) do 4 | @doc = 'Manage zabbix templates' 5 | 6 | ensurable do 7 | desc 'The basic property that the resource should be in.' 8 | defaultvalues 9 | defaultto :present 10 | 11 | def insync?(is) 12 | return false if is == :present && !template_xmls_match? 13 | 14 | super 15 | end 16 | 17 | def template_xmls_match? 18 | clean_xml(source_xml) == clean_xml(provider.xml) 19 | end 20 | 21 | def source_xml 22 | file = File.new(resource[:template_source], 'rb') 23 | file.read 24 | end 25 | 26 | def clean_xml(dirty) 27 | dirty.gsub(%r{>\s*}, '>').gsub(%r{\s*<}, '<').gsub(%r{.*}, 'DATEWASHERE') 28 | end 29 | 30 | def change_to_s(currentvalue, newvalue) 31 | return 'Template updated' if currentvalue == :present && newvalue == :present 32 | 33 | super 34 | end 35 | end 36 | 37 | newparam(:template_name, namevar: true) do 38 | desc 'The name of template.' 39 | end 40 | 41 | newparam(:template_source) do 42 | desc 'Template source file.' 43 | end 44 | 45 | newparam(:zabbix_version) do 46 | desc 'Zabbix version that the template will be installed on.' 47 | end 48 | 49 | newparam(:delete_missing_applications, boolean: true) do 50 | desc 'Delete applications from zabbix which are not in the template.' 51 | end 52 | 53 | newparam(:delete_missing_drules, boolean: true) do 54 | desc 'Delete discovery rules from zabbix which are not in the template.' 55 | end 56 | 57 | newparam(:delete_missing_graphs, boolean: true) do 58 | desc 'Delete graphs from zabbix which are not in the template.' 59 | end 60 | 61 | newparam(:delete_missing_httptests, boolean: true) do 62 | desc 'Delete web scenarios from zabbix which are not in the template.' 63 | end 64 | 65 | newparam(:delete_missing_items, boolean: true) do 66 | desc 'Delete items from zabbix which are not in the template.' 67 | end 68 | 69 | newparam(:delete_missing_templatescreens, boolean: true) do 70 | desc 'Delete templateScreens from zabbix which are not in the template.' 71 | end 72 | 73 | newparam(:delete_missing_triggers, boolean: true) do 74 | desc 'Delete triggers from zabbix which are not in the template.' 75 | end 76 | 77 | autorequire(:file) { '/etc/zabbix/api.conf' } 78 | end 79 | -------------------------------------------------------------------------------- /lib/puppet/type/zabbix_userparameters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..')) 4 | Puppet::Type.newtype(:zabbix_userparameters) do 5 | @doc = 'Manage zabbix user templates' 6 | 7 | ensurable do 8 | desc 'The basic property that the resource should be in.' 9 | defaultvalues 10 | defaultto :present 11 | end 12 | 13 | newparam(:name, namevar: true) do 14 | desc 'An unique name for this define.' 15 | end 16 | 17 | newparam(:hostname) do 18 | desc 'FQDN of the machine.' 19 | end 20 | 21 | newparam(:template) do 22 | desc 'Template which should be loaded for this host.' 23 | end 24 | 25 | autorequire(:file) { '/etc/zabbix/api.conf' } 26 | end 27 | -------------------------------------------------------------------------------- /manifests/database.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install the correct database and one or more users for correct usage 2 | # @param zabbix_type 3 | # The type of zabbix which is used: server or proxy. 4 | # This will determine what sql files will be loaded into database. 5 | # @param zabbix_web 6 | # This is the hostname of the server which is running the 7 | # zabbix-web package. This parameter is used when database_type = 8 | # mysql. When single node: localhost 9 | # @param zabbix_web_ip 10 | # This is the ip address of the server which is running the 11 | # zabbix-web package. This parameter is used when database_type = 12 | # postgresql. When single node: 127.0.0.1 13 | # @param zabbix_server 14 | # This is the FQDN for the host running zabbix-server. This parameter 15 | # is used when database_type = mysql. Default: localhost 16 | # @param zabbix_server_ip 17 | # This is the actual ip address of the host running zabbix-server 18 | # This parameter is used when database_type = postgresql. Default: 19 | # 127.0.0.1 20 | # @param zabbix_proxy 21 | # This is the FQDN for the host running zabbix-proxy. This parameter 22 | # is used when database_type = mysql. Default: localhost 23 | # @param zabbix_proxy_ip 24 | # This is the actual ip address of the host running zabbix-proxy 25 | # This parameter is used when database_type = postgresql. Default: 26 | # 127.0.0.1 27 | # @param manage_database 28 | # When set to true, it will create the database and will load 29 | # the sql files for basic setup. Otherwise you should do this manually. 30 | # @param database_type The database which is used: postgresql or mysql 31 | # @param database_schema_path The path to the directory containing the .sql schema files 32 | # @param database_name The name of the database. Default: zabbix-server 33 | # @param database_user The user which is used for connecting to the database 34 | # @param database_password The password of the database_user. 35 | # @param database_host The hostname of the server running the database. 36 | # @param database_host_ip IP of the machine the database runs on. 37 | # @param database_charset The default charset of the database. 38 | # @param database_collate The default collation of the database. 39 | # @param database_tablespace The tablespace the database will be created in. This setting only affects PostgreSQL databases. 40 | # @example The following is an example of an multiple host setup: 41 | # node 'wdpuppet04.dj-wasabi.local' { 42 | # # class { 'postgresql::server': 43 | # # listen_addresses => '192.168.20.14' 44 | # # } 45 | # class { 'mysql::server': 46 | # override_options => { 47 | # 'mysqld' => { 48 | # 'bind_address' => '192.168.20.14', 49 | # }, 50 | # }, 51 | # } 52 | # class { 'zabbix::database': 53 | # database_type => 'mysql', 54 | # #zabbix_front_ip => '192.168.20.12', 55 | # #zabbix_server_ip => '192.168.20.13', 56 | # zabbix_server => 'wdpuppet03.dj-wasabi.local', 57 | # zabbix_web => 'wdpuppet02.dj-wasabi.local', 58 | # } 59 | # } 60 | # 61 | # The above example is when database_type = mysql. When you want to 62 | # use the postgresql as database, uncomment the lines of postgresql 63 | # class and both *_ip parameters. Comment the mysql class and comment 64 | # the zabbix_server and zabbix_web parameter. 65 | # @author Werner Dijkerman ikben@werner-dijkerman.nl 66 | class zabbix::database ( 67 | $zabbix_type = 'server', 68 | $zabbix_web = $zabbix::params::zabbix_web, 69 | $zabbix_web_ip = $zabbix::params::zabbix_web_ip, 70 | $zabbix_server = $zabbix::params::zabbix_server, 71 | $zabbix_server_ip = $zabbix::params::zabbix_server_ip, 72 | $zabbix_proxy = $zabbix::params::zabbix_proxy, 73 | $zabbix_proxy_ip = $zabbix::params::zabbix_proxy_ip, 74 | $manage_database = $zabbix::params::manage_database, 75 | Zabbix::Databases $database_type = $zabbix::params::database_type, 76 | $database_schema_path = $zabbix::params::database_schema_path, 77 | $database_name = $zabbix::params::server_database_name, 78 | $database_user = $zabbix::params::server_database_user, 79 | $database_password = $zabbix::params::server_database_password, 80 | $database_host = $zabbix::params::server_database_host, 81 | $database_host_ip = $zabbix::params::server_database_host_ip, 82 | $database_charset = $zabbix::params::server_database_charset, 83 | $database_collate = $zabbix::params::server_database_collate, 84 | Optional[String[1]] $database_tablespace = $zabbix::params::server_database_tablespace, 85 | ) inherits zabbix::params { 86 | # So lets create the databases and load all files. This can only be 87 | # happen when manage_database is set to true (Default). 88 | if $manage_database == true { 89 | # Complain if database_tablespace is set and the database_type is not postgresql 90 | if ($database_tablespace and $database_type != 'postgresql') { 91 | fail("database_tablespace is set to '${database_tablespace}'. This setting is only useful for PostgreSQL databases.") 92 | } 93 | 94 | case $database_type { 95 | 'postgresql': { 96 | # This is the PostgreSQL part. 97 | 98 | include postgresql::server 99 | # Create the postgres database. 100 | postgresql::server::db { $database_name: 101 | user => $database_user, 102 | owner => $database_user, 103 | password => postgresql::postgresql_password($database_user, $database_password), 104 | tablespace => $database_tablespace, 105 | } 106 | 107 | # When database not in some server with zabbix server include pg_hba_rule to server 108 | if ($database_host_ip != $zabbix_server_ip) or ($zabbix_web_ip != $zabbix_server_ip) { 109 | postgresql::server::pg_hba_rule { 'Allow zabbix-server to access database': 110 | description => 'Open up postgresql for access from zabbix-server', 111 | type => 'host', 112 | database => $database_name, 113 | user => $database_user, 114 | address => "${zabbix_server_ip}/32", 115 | auth_method => 'md5', 116 | } 117 | } 118 | 119 | # When every component has its own server, we have to allow those servers to 120 | # access the database from the network. Postgresql allows this via the 121 | # pg_hba.conf file. As this file only accepts ip addresses, the ip address 122 | # of server and web has to be supplied as an parameter. 123 | if $zabbix_web_ip != $zabbix_server_ip { 124 | postgresql::server::pg_hba_rule { 'Allow zabbix-web to access database': 125 | description => 'Open up postgresql for access from zabbix-web', 126 | type => 'host', 127 | database => $database_name, 128 | user => $database_user, 129 | address => "${zabbix_web_ip}/32", 130 | auth_method => 'md5', 131 | } 132 | } # END if $zabbix_web_ip != $zabbix_server_ip 133 | 134 | # This is some specific action for the zabbix-proxy. This is due to better 135 | # parameter naming. 136 | if $zabbix_type == 'proxy' { 137 | postgresql::server::pg_hba_rule { 'Allow zabbix-proxy to access database': 138 | description => 'Open up postgresql for access from zabbix-proxy', 139 | type => 'host', 140 | database => $database_name, 141 | user => $database_user, 142 | address => "${zabbix_proxy_ip}/32", 143 | auth_method => 'md5', 144 | } 145 | } # END if $zabbix_type == 'proxy' 146 | } 147 | 'mysql': { 148 | # This is the MySQL part. 149 | include mysql::server 150 | 151 | # First we check what kind of zabbix component it is. We have to use clear names 152 | # as it may be confusing when you need to fill in the zabbix-proxy name into the 153 | # zabbix_server parameter. These are 2 different things. So we need to use an 154 | # if statement for this. 155 | if $zabbix_type == 'server' { 156 | mysql::db { $database_name: 157 | user => $database_user, 158 | password => $database_password, 159 | charset => $database_charset, 160 | collate => $database_collate, 161 | host => $zabbix_server, 162 | grant => ['all'], 163 | require => Class['mysql::server'], 164 | } 165 | } 166 | 167 | # And the proxy part. 168 | if $zabbix_type == 'proxy' { 169 | mysql::db { $database_name: 170 | user => $database_user, 171 | password => $database_password, 172 | charset => $database_charset, 173 | collate => $database_collate, 174 | host => $zabbix_proxy, 175 | grant => ['all'], 176 | require => Class['mysql::server'], 177 | } 178 | } 179 | 180 | # When the zabbix web and zabbix database aren't running on the same host, some 181 | # extra users/grants needs to be created. 182 | if $zabbix_web != $zabbix_server { 183 | mysql_user { "${database_user}@${zabbix_web}": 184 | ensure => 'present', 185 | password_hash => mysql::password($database_password), 186 | } 187 | 188 | # And this is the grant part. It will grant the users which is created earlier 189 | # to the zabbix-server database with all rights, like the user for the zabbix 190 | # -server itself. 191 | mysql_grant { "${database_user}@${zabbix_web}/${database_name}.*": 192 | ensure => 'present', 193 | options => ['GRANT'], 194 | privileges => ['ALL'], 195 | table => "${database_name}.*", 196 | user => "${database_user}@${zabbix_web}", 197 | require => [ 198 | Class['mysql::server'], 199 | Mysql::Db[$database_name], 200 | Mysql_user["${database_user}@${zabbix_web}"] 201 | ], 202 | } 203 | } # END if $zabbix_web != $zabbix_server 204 | } 205 | 'sqlite': { 206 | class { 'zabbix::database::sqlite': } 207 | } 208 | default: { 209 | fail('Unrecognized database type for server.') 210 | } 211 | } # END case $database_type 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /manifests/database/mysql.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install and load the sql files for the tables and other data which is needed for zabbix. 2 | # @api private 3 | # @param zabbix_type Zabbix component type. Can be one of: proxy, server 4 | # @param zabbix_version This is the zabbix version 5 | # @param database_schema_path The path to the directory containing the .sql schema files 6 | # @param database_name Name of the database to connect to 7 | # @param database_user Username to use to connect to the database 8 | # @param database_password Password to use to connect to the database 9 | # @param database_host Hostname to use to connect to the database 10 | # @param database_port Database port to be used for the import process. 11 | # @param database_path Path to the database executable 12 | # @author Werner Dijkerman 13 | class zabbix::database::mysql ( 14 | $zabbix_type = '', 15 | $zabbix_version = $zabbix::params::zabbix_version, 16 | $database_schema_path = '', 17 | $database_name = '', 18 | $database_user = '', 19 | $database_password = '', 20 | $database_host = '', 21 | Optional[Stdlib::Port::Unprivileged] $database_port = undef, 22 | $database_path = $zabbix::params::database_path, 23 | ) inherits zabbix::params { 24 | assert_private() 25 | 26 | if ($database_schema_path == false) or ($database_schema_path == '') { 27 | $schema_path = '/usr/share/zabbix-sql-scripts/mysql/' 28 | } 29 | else { 30 | $schema_path = $database_schema_path 31 | } 32 | 33 | if $database_port != undef { 34 | $port = "-P ${database_port} " 35 | } else { 36 | $port = '' 37 | } 38 | 39 | case $zabbix_type { 40 | 'proxy': { 41 | $zabbix_proxy_create_sql = "cd ${schema_path} && mysql -h '${database_host}' -u '${database_user}' -p'${database_password}' ${port}-D '${database_name}' < proxy.sql && touch /etc/zabbix/.schema.done" 42 | } 43 | default: { 44 | $zabbix_server_create_sql = "cd ${schema_path} && if [ -f server.sql.gz ]; then gunzip -f server.sql.gz ; fi && mysql -h '${database_host}' -u '${database_user}' -p'${database_password}' ${port}-D '${database_name}' < server.sql && touch /etc/zabbix/.schema.done" 45 | } 46 | } 47 | 48 | # Loading the sql files. 49 | case $zabbix_type { 50 | 'proxy' : { 51 | exec { 'zabbix_proxy_create.sql': 52 | command => $zabbix_proxy_create_sql, 53 | path => "/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:${database_path}", 54 | unless => 'test -f /etc/zabbix/.schema.done', 55 | provider => 'shell', 56 | } 57 | } 58 | 'server' : { 59 | exec { 'zabbix_server_create.sql': 60 | command => $zabbix_server_create_sql, 61 | path => "/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:${database_path}", 62 | unless => 'test -f /etc/zabbix/.schema.done', 63 | provider => 'shell', 64 | } 65 | } 66 | default : { 67 | fail 'We do not work.' 68 | } 69 | } # END case $zabbix_type 70 | } 71 | -------------------------------------------------------------------------------- /manifests/database/postgresql.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install and load the sql files for the tables and other data which is needed for zabbix. 2 | # @api private 3 | # @param zabbix_type Zabbix component type. Can be one of: proxy, server 4 | # @param zabbix_version This is the zabbix version 5 | # @param database_schema_path The path to the directory containing the .sql schema files 6 | # @param database_name Name of the database to connect to 7 | # @param database_user Username to use to connect to the database 8 | # @param database_password Password to use to connect to the database 9 | # @param database_host Hostname to use to connect to the database 10 | # @param database_port Database port to be used for the import process. 11 | # @param database_path Path to the database executable 12 | # @author Werner Dijkerman 13 | class zabbix::database::postgresql ( 14 | $zabbix_type = '', 15 | $zabbix_version = $zabbix::params::zabbix_version, 16 | $database_schema_path = '', 17 | $database_name = '', 18 | $database_user = '', 19 | $database_password = '', 20 | $database_host = '', 21 | Stdlib::Port::Unprivileged $database_port = 5432, 22 | $database_path = $zabbix::params::database_path, 23 | ) inherits zabbix::params { 24 | assert_private() 25 | 26 | if $database_schema_path != false and $database_schema_path != '' { 27 | $schema_path = $database_schema_path 28 | } else { 29 | $schema_path = '/usr/share/zabbix-sql-scripts/postgresql/' 30 | } 31 | 32 | $done_file = '/etc/zabbix/.schema.done' 33 | $schema_file = case $zabbix_type { 34 | 'proxy': { 35 | 'proxy.sql' 36 | } 37 | default: { 38 | 'server.sql' 39 | } 40 | } 41 | 42 | $command = "cd ${schema_path} && if [ -f ${schema_file}.gz ]; then zcat ${schema_file}.gz | psql ; else psql -f ${schema_file}; fi && touch ${done_file}" 43 | $exec_env = [ 44 | "PGHOST=${database_host}", 45 | "PGPORT=${database_port}", 46 | "PGUSER=${database_user}", 47 | "PGPASSWORD=${database_password}", 48 | "PGDATABASE=${database_name}", 49 | ] 50 | 51 | exec { 'zabbix_create.sql': 52 | command => $command, 53 | path => "/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:${database_path}", 54 | creates => $done_file, 55 | provider => 'shell', 56 | environment => $exec_env, 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /manifests/database/sqlite.pp: -------------------------------------------------------------------------------- 1 | # @summary Class to handle sqlite database installations zabbix will automatically create a sqlite schema if one does not already exist. 2 | # @author Werner Dijkerman 3 | class zabbix::database::sqlite () {} 4 | -------------------------------------------------------------------------------- /manifests/javagateway.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install and configure the zabbix-agent deamon 2 | # @param zabbix_version This is the zabbix version. 3 | # @param zabbix_package_state The state of the package that needs to be installed: present or latest. 4 | # @param manage_firewall When true, it will create iptables rules. 5 | # @param manage_repo When true, it will create repository for installing the javagateway. 6 | # @param pidfile Name of pid file. 7 | # @param listenip List of comma delimited ip addresses that the agent should listen on. 8 | # @param listenport Agent will listen on this port for connections from the server. 9 | # @param startpollers Number of worker threads to start. 10 | # @param timeout Number of worker threads to start. 11 | # @example 12 | # class { 'zabbix::javagateway': 13 | # zabbix_version => '6.0', 14 | # } 15 | # @author Werner Dijkerman ikben@werner-dijkerman.nl 16 | class zabbix::javagateway ( 17 | $zabbix_version = $zabbix::params::zabbix_version, 18 | $zabbix_package_state = $zabbix::params::zabbix_package_state, 19 | Boolean $manage_firewall = $zabbix::params::manage_firewall, 20 | Boolean $manage_repo = $zabbix::params::manage_repo, 21 | $pidfile = $zabbix::params::javagateway_pidfile, 22 | $listenip = $zabbix::params::javagateway_listenip, 23 | $listenport = $zabbix::params::javagateway_listenport, 24 | $startpollers = $zabbix::params::javagateway_startpollers, 25 | $timeout = $zabbix::params::javagateway_timeout, 26 | ) inherits zabbix::params { 27 | # Fix for pid file. Is different in Zabbix (4, 5) and 6 28 | $real_pidfile = $zabbix_version ? { 29 | /^[45]\.[024]/ => pick($pidfile, '/var/run/zabbix/zabbix_java.pid'), 30 | /^[6]\.[024]/ => pick($pidfile, '/var/run/zabbix/zabbix_java_gateway.pid'), 31 | } 32 | # Only include the repo class if it has not yet been included 33 | unless defined(Class['Zabbix::Repo']) { 34 | class { 'zabbix::repo': 35 | manage_repo => $manage_repo, 36 | zabbix_version => $zabbix_version, 37 | } 38 | } 39 | 40 | # Installing the package 41 | package { 'zabbix-java-gateway': 42 | ensure => $zabbix_package_state, 43 | require => Class['zabbix::repo'], 44 | tag => 'zabbix', 45 | } 46 | 47 | # Configuring the zabbix-javagateway configuration file 48 | file { '/etc/zabbix/zabbix_java_gateway.conf': 49 | ensure => file, 50 | owner => 'zabbix', 51 | group => 'zabbix', 52 | mode => '0640', 53 | notify => Service['zabbix-java-gateway'], 54 | require => Package['zabbix-java-gateway'], 55 | replace => true, 56 | content => template('zabbix/zabbix_java_gateway.conf.erb'), 57 | } 58 | 59 | # Controlling the 'zabbix-java-gateway' service 60 | service { 'zabbix-java-gateway': 61 | ensure => running, 62 | enable => true, 63 | hasstatus => true, 64 | hasrestart => true, 65 | require => [ 66 | Package['zabbix-java-gateway'], 67 | File['/etc/zabbix/zabbix_java_gateway.conf'] 68 | ], 69 | } 70 | 71 | # Manage firewall 72 | if $manage_firewall { 73 | firewall { '152 zabbix-javagateway': 74 | dport => $listenport, 75 | proto => 'tcp', 76 | jump => 'accept', 77 | state => ['NEW','RELATED', 'ESTABLISHED'], 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /manifests/repo.pp: -------------------------------------------------------------------------------- 1 | # @summary If enabled, this will install the repository used for installing zabbix 2 | # @param manage_repo When true, it will create repository for installing the server. 3 | # @param manage_apt Whether the module should manage apt repositories for Debian based systems. 4 | # @param zabbix_version This is the zabbix version. 5 | # @param repo_location A custom repo location (e.g. your own mirror) 6 | # @param repo_gpg_key_location 7 | # A custom repo GPG key location (e.g. an airlocked copy of the gpg key) 8 | # @param frontend_repo_location A custom repo location for frontend package. 9 | # @param unsupported_repo_location 10 | # A custom repo location for unsupported content (e.g. your own mirror) 11 | # Currently only supported under RedHat based systems. 12 | # @param unsupported_repo_gpg_key_location 13 | # A custom repo GPG key location (e.g. an airlocked copy of the gpg key) 14 | # @author Werner Dijkerman 15 | # @author Tim Meusel 16 | class zabbix::repo ( 17 | Boolean $manage_repo = $zabbix::params::manage_repo, 18 | Boolean $manage_apt = $zabbix::params::manage_apt, 19 | Optional[Stdlib::HTTPUrl] $repo_location = $zabbix::params::repo_location, 20 | Optional[Stdlib::HTTPUrl] $repo_gpg_key_location = $zabbix::params::repo_gpg_key_location, 21 | Optional[Stdlib::HTTPUrl] $frontend_repo_location = $zabbix::params::frontend_repo_location, 22 | Optional[Stdlib::HTTPUrl] $unsupported_repo_location = $zabbix::params::unsupported_repo_location, 23 | Optional[Stdlib::HTTPUrl] $unsupported_repo_gpg_key_location = $zabbix::params::unsupported_repo_gpg_key_location, 24 | String[1] $zabbix_version = $zabbix::params::zabbix_version, 25 | ) inherits zabbix::params { 26 | if $manage_repo { 27 | case $facts['os']['family'] { 28 | 'RedHat': { 29 | $majorrelease = $facts['os']['release']['major'] 30 | if versioncmp($zabbix_version, '7.0') >= 0 { 31 | $_gpgkey_zabbix = $repo_gpg_key_location ? { 32 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-B5333005', 33 | default => "${repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-B5333005", 34 | } 35 | if versioncmp(fact('os.release.major'), '9') >= 0 { 36 | $_gpgkey_nonsupported = $unsupported_repo_gpg_key_location ? { 37 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-08EFA7DD', 38 | default => "${unsupported_repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-08EFA7DD", 39 | } 40 | } else { 41 | $_gpgkey_nonsupported = $unsupported_repo_gpg_key_location ? { 42 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-B5333005', 43 | default => "${unsupported_repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-B5333005", 44 | } 45 | } 46 | } elsif versioncmp(fact('os.release.major'), '9') >= 0 { 47 | $_gpgkey_zabbix = $repo_gpg_key_location ? { 48 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-08EFA7DD', 49 | default => "${repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-08EFA7DD", 50 | } 51 | $_gpgkey_nonsupported = $unsupported_repo_gpg_key_location ? { 52 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-08EFA7DD', 53 | default => "${unsupported_repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-08EFA7DD", 54 | } 55 | } else { 56 | $_gpgkey_zabbix = $repo_gpg_key_location ? { 57 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-A14FE591', 58 | default => "${repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-A14FE591", 59 | } 60 | $_gpgkey_nonsupported = $unsupported_repo_gpg_key_location ? { 61 | undef => 'https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-79EA5ED4', 62 | default => "${unsupported_repo_gpg_key_location}/RPM-GPG-KEY-ZABBIX-79EA5ED4", 63 | } 64 | } 65 | 66 | $_repo_location = $repo_location ? { 67 | undef => "https://repo.zabbix.com/zabbix/${zabbix_version}/rhel/${majorrelease}/\$basearch/", 68 | default => $repo_location, 69 | } 70 | 71 | yumrepo { 'zabbix': 72 | name => "Zabbix_${majorrelease}_${facts['os']['architecture']}", 73 | descr => "Zabbix_${majorrelease}_${facts['os']['architecture']}", 74 | baseurl => $_repo_location, 75 | gpgcheck => '1', 76 | gpgkey => $_gpgkey_zabbix, 77 | priority => '1', 78 | } 79 | 80 | $_unsupported_repo_location = $unsupported_repo_location ? { 81 | undef => "https://repo.zabbix.com/non-supported/rhel/${majorrelease}/\$basearch/", 82 | default => $unsupported_repo_location, 83 | } 84 | 85 | yumrepo { 'zabbix-nonsupported': 86 | name => "Zabbix_nonsupported_${majorrelease}_${facts['os']['architecture']}", 87 | descr => "Zabbix_nonsupported_${majorrelease}_${facts['os']['architecture']}", 88 | baseurl => $_unsupported_repo_location, 89 | gpgcheck => '1', 90 | gpgkey => $_gpgkey_nonsupported, 91 | priority => '1', 92 | } 93 | } 94 | 'Debian': { 95 | if ($manage_apt) { 96 | # We would like to provide the repos with https urls instead of http 97 | # this requires the apt-transport-https package, but we don't want to manage 98 | # that package here. That should be handled in a profile :( 99 | # somebody should implement https here but make it optional 100 | include apt 101 | } 102 | 103 | if ($facts['os']['distro']['id'] == 'Raspbian') { 104 | $operatingsystem = 'raspbian' 105 | } elsif ($facts['os']['architecture'] in ['arm64', 'aarch64']) { 106 | # arm64 is the Debian name, but some facter versions report aarch64 instead 107 | $operatingsystem = "${downcase($facts['os']['name'])}-arm64" 108 | } else { 109 | $operatingsystem = downcase($facts['os']['name']) 110 | } 111 | case $facts['os']['release']['full'] { 112 | /\/sid$/: { $releasename = regsubst($facts['os']['release']['full'], '/sid$', '') } 113 | default: { $releasename = $facts['os']['distro']['codename'] } 114 | } 115 | 116 | $_repo_location = $repo_location ? { 117 | undef => "http://repo.zabbix.com/zabbix/${zabbix_version}/${operatingsystem}/", 118 | default => $repo_location, 119 | } 120 | 121 | $_gpgkey_zabbix = $repo_gpg_key_location ? { 122 | undef => 'https://repo.zabbix.com/zabbix-official-repo.key', 123 | default => "${repo_gpg_key_location}/zabbix-official-repo.key", 124 | } 125 | 126 | apt::key { 'zabbix-FBABD5F': 127 | id => 'FBABD5FB20255ECAB22EE194D13D58E479EA5ED4', 128 | source => $_gpgkey_zabbix, 129 | } 130 | apt::key { 'zabbix-A1848F5': 131 | id => 'A1848F5352D022B9471D83D0082AB56BA14FE591', 132 | source => $_gpgkey_zabbix, 133 | } 134 | apt::key { 'zabbix-4C3D6F2': 135 | id => '4C3D6F2CC75F5146754FC374D913219AB5333005', 136 | source => $_gpgkey_zabbix, 137 | } 138 | 139 | # Debian 11 provides Zabbix 5.0 by default. This can cause problems for 4.0 versions 140 | $pinpriority = $facts['os']['release']['major'] ? { 141 | '11' => 1000, 142 | default => undef, 143 | } 144 | apt::source { 'zabbix': 145 | location => $_repo_location, 146 | repos => 'main', 147 | release => $releasename, 148 | pin => $pinpriority, 149 | require => [ 150 | Apt_key['zabbix-FBABD5F'], 151 | Apt_key['zabbix-A1848F5'], 152 | Apt_key['zabbix-4C3D6F2'], 153 | ], 154 | } 155 | 156 | Apt::Source['zabbix'] -> Package<|tag == 'zabbix'|> 157 | Class['Apt::Update'] -> Package<|tag == 'zabbix'|> 158 | } 159 | default: { 160 | fail("Managing a repo on ${facts['os']['family']} is currently not implemented") 161 | } 162 | } 163 | } # end if ($manage_repo) 164 | } 165 | -------------------------------------------------------------------------------- /manifests/resources/agent.pp: -------------------------------------------------------------------------------- 1 | # @summary This will create resources into puppetdb for automatically configuring agent into zabbix front-end. 2 | # @param hostname Hostname of the machine 3 | # @param ipaddress The IP address of the machine running zabbix agent. 4 | # @param use_ip Use ipadress instead of dns to connect. 5 | # @param port The port that the zabbix agent is listening on. 6 | # @param groups An array of groups the host belongs to. 7 | # @param group_create Whether to create hostgroup if missing. 8 | # @param templates List of templates which should be attached to this host. 9 | # @param macros Array of hashes (macros) which should be attached to this host. 10 | # @param proxy Whether it is monitored by an proxy or not. 11 | # @param interfacetype Internally used identifier for the host interface. 12 | # @param interfacedetails Hash with interface details for SNMP when interface type is 2. 13 | # @param tls_connect How the server must connect to the agent 14 | # @param tls_accept How the agent can connect to the server 15 | # @param tls_issuer Issuer of the certificate that is allowed to talk with the serve 16 | # @param tls_subject Subject of the certificate that is allowed to talk with the server 17 | class zabbix::resources::agent ( 18 | $hostname = undef, 19 | $ipaddress = undef, 20 | $use_ip = undef, 21 | $port = undef, 22 | Optional[Array[String[1]]] $groups = undef, 23 | $group_create = undef, 24 | $templates = undef, 25 | $macros = undef, 26 | $proxy = undef, 27 | $interfacetype = 1, 28 | Variant[Array, Hash] $interfacedetails = [], 29 | Optional[Enum['unencrypted','psk','cert']] $tls_connect = undef, 30 | Optional[Enum['unencrypted','psk','cert']] $tls_accept = undef, 31 | Optional[String[1]] $tls_issuer = undef, 32 | Optional[String[1]] $tls_subject = undef, 33 | ) { 34 | @@zabbix_host { $hostname: 35 | ipaddress => $ipaddress, 36 | use_ip => $use_ip, 37 | port => $port, 38 | groups => $groups, 39 | group_create => $group_create, 40 | templates => $templates, 41 | macros => $macros, 42 | proxy => $proxy, 43 | interfacetype => $interfacetype, 44 | interfacedetails => $interfacedetails, 45 | tls_connect => $tls_connect, 46 | tls_accept => $tls_accept, 47 | tls_issuer => $tls_issuer, 48 | tls_subject => $tls_subject, 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /manifests/resources/proxy.pp: -------------------------------------------------------------------------------- 1 | # @summary This will create resources into puppetdb for automatically configuring proxy agent into zabbix front-end. 2 | # @param hostname Hostname of the proxy. 3 | # @param ipaddress The IP address of the machine running zabbix proxy. 4 | # @param use_ip Whether to use ipadress instead of dns to connect. 5 | # @param mode The kind of mode the proxy running. Active (0) or passive (1). 6 | # @param port The port that the zabbix proxy is listening on. 7 | class zabbix::resources::proxy ( 8 | $hostname = undef, 9 | $ipaddress = undef, 10 | $use_ip = undef, 11 | $mode = undef, 12 | $port = undef, 13 | ) { 14 | @@zabbix_proxy { $hostname: 15 | ipaddress => $ipaddress, 16 | use_ip => $use_ip, 17 | mode => $mode, 18 | port => $port, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /manifests/resources/template.pp: -------------------------------------------------------------------------------- 1 | # @summary This will create resources into puppetdb for automatically configuring agent into zabbix front-end. 2 | # @param template_dir The directory containing zabbix templates 3 | # @param template_name The name of template. 4 | # @param template_source Template source file. 5 | # @param zabbix_version Zabbix version that the template will be installed on. 6 | # @param delete_missing_applications Deletes applications from zabbix that are not in the template when set to true 7 | # @param delete_missing_drules Deletes discovery rules from zabbix that are not in the template when set to true 8 | # @param delete_missing_graphs Deletes graphs from zabbix that are not in the template when set to true 9 | # @param delete_missing_httptests Deletes web-scenarios from zabbix that are not in the template when set to true 10 | # @param delete_missing_items Deletes items from zabbix that are not in the template when set to true 11 | # @param delete_missing_templatescreens Deletes template-screens from zabbix that are not in the template when set to true 12 | # @param delete_missing_triggers Deletes triggers from zabbix that are not in the template when set to true 13 | define zabbix::resources::template ( 14 | $template_dir = $zabbix::params::zabbix_template_dir, 15 | $template_name = $title, 16 | $template_source = '', 17 | $zabbix_version = $zabbix::params::zabbix_version, 18 | Boolean $delete_missing_applications = false, 19 | Boolean $delete_missing_drules = false, 20 | Boolean $delete_missing_graphs = false, 21 | Boolean $delete_missing_httptests = false, 22 | Boolean $delete_missing_items = false, 23 | Boolean $delete_missing_templatescreens = false, 24 | Boolean $delete_missing_triggers = false, 25 | ) { 26 | file { "${template_dir}/${template_name}.xml": 27 | ensure => file, 28 | owner => 'zabbix', 29 | group => 'zabbix', 30 | source => $template_source, 31 | } 32 | 33 | @@zabbix_template { $template_name: 34 | template_source => "${template_dir}/${template_name}.xml", 35 | zabbix_version => $zabbix_version, 36 | require => File["${template_dir}/${template_name}.xml"], 37 | delete_missing_applications => $delete_missing_applications, 38 | delete_missing_drules => $delete_missing_drules, 39 | delete_missing_graphs => $delete_missing_graphs, 40 | delete_missing_httptests => $delete_missing_httptests, 41 | delete_missing_items => $delete_missing_items, 42 | delete_missing_templatescreens => $delete_missing_templatescreens, 43 | delete_missing_triggers => $delete_missing_triggers, 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /manifests/resources/userparameters.pp: -------------------------------------------------------------------------------- 1 | # @summary This will create resources into puppetdb for automatically configuring agent into zabbix front-end. 2 | # @param ensure Ensure resource. 3 | # @param hostname Hostname of the machine. 4 | # @param template Template which should be attached to this host. 5 | define zabbix::resources::userparameters ( 6 | $ensure, 7 | $hostname, 8 | $template, 9 | ) { 10 | @@zabbix_userparameters { "${hostname}_${name}": 11 | ensure => $ensure, 12 | hostname => $hostname, 13 | template => $template, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /manifests/resources/web.pp: -------------------------------------------------------------------------------- 1 | # @summary This will load all zabbix related items from the puppet database and uses the zabbixapi gem to add/configure hosts via the zabbix-api 2 | # @param zabbix_url Url on which zabbix is available. 3 | # @param zabbix_user API username. 4 | # @param zabbix_pass API password. 5 | # @param apache_use_ssl Whether to use ssl or not. 6 | class zabbix::resources::web ( 7 | String[1] $zabbix_url, 8 | String[1] $zabbix_user, 9 | String[1] $zabbix_pass, 10 | Boolean $apache_use_ssl, 11 | ) { 12 | file { '/etc/zabbix/api.conf': 13 | ensure => file, 14 | owner => 'root', 15 | group => 'root', 16 | mode => '0400', 17 | content => epp('zabbix/api.conf.epp', 18 | { 19 | zabbix_url => $zabbix_url, 20 | zabbix_user => $zabbix_user, 21 | zabbix_pass => $zabbix_pass, 22 | apache_use_ssl => $apache_use_ssl, 23 | } 24 | ), 25 | } 26 | 27 | Zabbix_proxy <<| |>> { 28 | require => [ 29 | Service['zabbix-server'], 30 | Package['zabbixapi'], 31 | File['/etc/zabbix/api.conf'], 32 | ], 33 | } 34 | -> Zabbix_template <<| |>> 35 | -> Zabbix_host <<| |>> 36 | -> Zabbix_userparameters <<| |>> 37 | } 38 | -------------------------------------------------------------------------------- /manifests/sender.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install and configure the zabbix-agent deamon 2 | # @param zabbix_version This is the zabbix version. 3 | # @param zabbix_package_state The state of the package that needs to be installed: present or latest. 4 | # @param manage_repo When true, it will create repository for installing the agent. 5 | class zabbix::sender ( 6 | $zabbix_version = $zabbix::params::zabbix_version, 7 | $zabbix_package_state = $zabbix::params::zabbix_package_state, 8 | $manage_repo = $zabbix::params::manage_repo, 9 | ) inherits zabbix::params { 10 | # Only include the repo class if it has not yet been included 11 | unless defined(Class['Zabbix::Repo']) { 12 | class { 'zabbix::repo': 13 | manage_repo => $manage_repo, 14 | zabbix_version => $zabbix_version, 15 | } 16 | } 17 | 18 | # Installing the package 19 | package { 'zabbix-sender': 20 | ensure => $zabbix_package_state, 21 | require => Class['zabbix::repo'], 22 | tag => 'zabbix', 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /manifests/startup.pp: -------------------------------------------------------------------------------- 1 | # @summary This manage the zabbix related service startup script. 2 | # @param pidfile Location of the PID file 3 | # @param agent_configfile_path Location of Zabbix's agent configuration file 4 | # @param server_configfile_path Location of Zabbix's server configuration file 5 | # @param database_type 6 | # Type of database. Can use the following 2 databases: 7 | # - postgresql 8 | # - mysql 9 | # @param zabbix_user User the zabbix service will run as 10 | # @param additional_service_params Additional parameters to pass to the service 11 | # @param service_type Systemd service type 12 | # @param manage_database When true, it will configure the database and execute the sql scripts. 13 | # @param service_name Name of the service. Defaults to the resource name 14 | # @example 15 | # zabbix::startup { 'agent': } 16 | # 17 | # @example 18 | # zabbix::startup { 'server': } 19 | # 20 | define zabbix::startup ( 21 | Optional[Stdlib::Absolutepath] $pidfile = undef, 22 | Optional[Stdlib::Absolutepath] $agent_configfile_path = undef, 23 | Optional[Stdlib::Absolutepath] $server_configfile_path = undef, 24 | Optional[Zabbix::Databases] $database_type = undef, 25 | Optional[String] $zabbix_user = undef, 26 | Optional[String[1]] $additional_service_params = undef, 27 | String $service_type = 'simple', 28 | Optional[Boolean] $manage_database = undef, 29 | Optional[String] $service_name = $name, 30 | ) { 31 | case $title.downcase { 32 | /agent/: { 33 | assert_type(Stdlib::Absolutepath, $agent_configfile_path) 34 | } 35 | /server/: { 36 | assert_type(Stdlib::Absolutepath, $server_configfile_path) 37 | assert_type(Zabbix::Databases, $database_type) 38 | assert_type(Boolean, $manage_database) 39 | } 40 | default: { 41 | fail('we currently only support a title that contains agent or server') 42 | } 43 | } 44 | # provided by camp2camp/systemd 45 | if $facts['systemd'] { 46 | contain systemd 47 | systemd::unit_file { "${name}.service": 48 | content => template("zabbix/${service_name}-systemd.init.erb"), 49 | } 50 | file { "/etc/init.d/${name}": 51 | ensure => absent, 52 | } 53 | } elsif $facts['os']['family'] in ['Debian', 'RedHat'] { 54 | # Currently other osfamily without systemd is not supported 55 | $osfamily_downcase = downcase($facts['os']['family']) 56 | file { "/etc/init.d/${service_name}": 57 | ensure => file, 58 | mode => '0755', 59 | content => template("zabbix/${name}-${osfamily_downcase}.init.erb"), 60 | } 61 | } elsif $facts['os']['family'] in ['AIX'] { 62 | file { "/etc/rc.d/init.d/${service_name}": 63 | ensure => file, 64 | mode => '0755', 65 | content => epp('zabbix/zabbix-agent-aix.init.epp', { 'pidfile' => $pidfile, 'agent_configfile_path' => $agent_configfile_path, 'zabbix_user' => $zabbix_user }), 66 | } 67 | file { "/etc/rc.d/rc2.d/S999${service_name}": 68 | ensure => 'link', 69 | target => "/etc/rc.d/init.d/${service_name}", 70 | } 71 | } elsif ($facts['os']['family'] == 'windows') { 72 | exec { "install_agent_${name}": 73 | command => "& 'C:\\Program Files\\Zabbix Agent\\zabbix_agentd.exe' --config ${agent_configfile_path} --install", 74 | onlyif => "if (Get-WmiObject -Class Win32_Service -Filter \"Name='${name}'\"){exit 1}", 75 | provider => powershell, 76 | notify => Service[$name], 77 | } 78 | } else { 79 | fail('We currently only support Debian, FreeBSD, Redhat, AIX and Windows osfamily as non-systemd') 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /manifests/template.pp: -------------------------------------------------------------------------------- 1 | # @summary This will upload an Zabbix Template (XML format) 2 | # @param templ_name The name of the template. This name will be found in the Web interface 3 | # @param templ_source The location of the XML file wich needs to be imported. 4 | # @param zabbix_version The Zabbix version on which the template will be installed on. 5 | # @param delete_missing_applications Deletes applications from zabbix that are not in the template when set to true 6 | # @param delete_missing_drules Deletes discovery rules from zabbix that are not in the template when set to true 7 | # @param delete_missing_graphs Deletes graphs from zabbix that are not in the template when set to true 8 | # @param delete_missing_httptests Deletes web-scenarios from zabbix that are not in the template when set to true 9 | # @param delete_missing_items Deletes items from zabbix that are not in the template when set to true 10 | # @param delete_missing_templatescreens Deletes template-screens from zabbix that are not in the template when set to true 11 | # @param delete_missing_triggers Deletes triggers from zabbix that are not in the template when set to true 12 | # @example 13 | # zabbix::template { 'Template App MySQL': 14 | # templ_source => 'puppet:///modules/zabbix/MySQL.xml' 15 | # } 16 | # @author Vladislav Tkatchev 17 | define zabbix::template ( 18 | $templ_name = $title, 19 | $templ_source = '', 20 | String[1] $zabbix_version = $zabbix::params::zabbix_version, 21 | Boolean $delete_missing_applications = false, 22 | Boolean $delete_missing_drules = false, 23 | Boolean $delete_missing_graphs = false, 24 | Boolean $delete_missing_httptests = false, 25 | Boolean $delete_missing_items = false, 26 | Boolean $delete_missing_templatescreens = false, 27 | Boolean $delete_missing_triggers = false, 28 | ) { 29 | zabbix::resources::template { $templ_name: 30 | template_name => $templ_name, 31 | template_source => $templ_source, 32 | zabbix_version => $zabbix_version, 33 | delete_missing_applications => $delete_missing_applications, 34 | delete_missing_drules => $delete_missing_drules, 35 | delete_missing_graphs => $delete_missing_graphs, 36 | delete_missing_httptests => $delete_missing_httptests, 37 | delete_missing_items => $delete_missing_items, 38 | delete_missing_templatescreens => $delete_missing_templatescreens, 39 | delete_missing_triggers => $delete_missing_triggers, 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /manifests/userparameter.pp: -------------------------------------------------------------------------------- 1 | # @summary This class can be used when you use hiera or The Foreman. With this tools you can't use and define. This make use of "create_resources". 2 | # @param data This is the data in YAML format 3 | # @example 4 | # zabbix::userparameter::data: 5 | # MySQL: 6 | # content: UserParameter=mysql.ping,mysqladmin -uroot ping | grep -c alive 7 | # @author Werner Dijkerman 8 | class zabbix::userparameter ( 9 | Hash $data = {}, 10 | ) { 11 | $_data = hiera_hash('zabbix::userparameter::data', $data) 12 | $_data.each |$key,$value| { 13 | zabbix::userparameters { $key: 14 | * => $value, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /manifests/userparameters.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install an userparameters file with keys for items that can be checked with zabbix. 2 | # @param ensure If the userparameter should be `present` or `absent` 3 | # @param source File which holds several userparameter entries. 4 | # @param content When you have 1 userparameter entry which you want to install. 5 | # @param script Low level discovery (LLD) script. 6 | # @param script_ext The script extention. Should be started with the dot. Like: .sh .bat .py 7 | # @param template 8 | # When you use exported resources (when manage_resources is set to true on other components) 9 | # you'll can add the name of the template which correspondents with the 'content' or 10 | # 'source' which you add. The template will be added to the host. 11 | # @param script_dir 12 | # When 'script' is used, this parameter can provide the directly where this script needs to be placed. Default: '/usr/bin' 13 | # @param config_mode 14 | # When 'config_mode' is used, this parameter can provide the mode of the config file who will be created 15 | # to keep some credidentials private. Default: '0644' 16 | # @example 17 | # zabbix::userparameters { 'mysql': 18 | # source => 'puppet:///modules/zabbix/mysqld.conf', 19 | # } 20 | # @example 21 | # zabbix::userparameters { 'mysql': 22 | # content => 'UserParameter=mysql.ping,mysqladmin -uroot ping | grep -c alive', 23 | # } 24 | # @example Or when using exported resources (manage_resources is set to true) 25 | # zabbix::userparameters { 'mysql': 26 | # source => 'puppet:///modules/zabbix/mysqld.conf', 27 | # template => 'Template App MySQL', 28 | # } 29 | # @author Werner Dijkerman 30 | define zabbix::userparameters ( 31 | Enum['present', 'absent'] $ensure = 'present', 32 | Optional[Stdlib::Filesource] $source = undef, 33 | Optional[String[1]] $content = undef, 34 | Optional[Stdlib::Filesource] $script = undef, 35 | Optional[String[1]] $script_ext = undef, 36 | Optional[String[1]] $template = undef, 37 | Stdlib::Absolutepath $script_dir = '/usr/bin', 38 | Stdlib::Filemode $config_mode = '0644', 39 | ) { 40 | include zabbix::agent 41 | $include_dir = $zabbix::agent::include_dir 42 | $zabbix_package_agent = $zabbix::agent::zabbix_package_agent 43 | $agent_config_owner = $zabbix::agent::agent_config_owner 44 | $agent_config_group = $zabbix::agent::agent_config_group 45 | $agent_servicename = $zabbix::agent::servicename 46 | 47 | if $source { 48 | file { "${include_dir}/${name}.conf": 49 | ensure => $ensure, 50 | owner => $agent_config_owner, 51 | group => $agent_config_group, 52 | mode => $config_mode, 53 | source => $source, 54 | notify => Service[$agent_servicename], 55 | require => Package[$zabbix_package_agent], 56 | } 57 | } 58 | 59 | if $content { 60 | file { "${include_dir}/${name}.conf": 61 | ensure => $ensure, 62 | owner => $agent_config_owner, 63 | group => $agent_config_group, 64 | mode => $config_mode, 65 | content => $content, 66 | notify => Service[$agent_servicename], 67 | require => Package[$zabbix_package_agent], 68 | } 69 | } 70 | 71 | if $script { 72 | file { "${script_dir}/${name}${script_ext}": 73 | ensure => $ensure, 74 | owner => $agent_config_owner, 75 | group => $agent_config_group, 76 | mode => '0755', 77 | source => $script, 78 | notify => Service[$agent_servicename], 79 | require => Package[$zabbix_package_agent], 80 | } 81 | } 82 | 83 | # If template is defined, it means we have an template in zabbix 84 | # which needs to be loaded for this host. When exported resources is 85 | # used/enabled, we do this automatically. 86 | if $template { 87 | zabbix::resources::userparameters { "${facts['networking']['hostname']}_${name}": 88 | ensure => $ensure, 89 | hostname => $facts['networking']['fqdn'], 90 | template => $template, 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /manifests/zabbixapi.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install the zabbixapi gem. 2 | # 3 | # @param zabbix_version This is the zabbix version. 4 | # @param puppetgem Provider for the zabbixapi gem package. 5 | class zabbix::zabbixapi ( 6 | $zabbix_version = $zabbix::params::zabbix_version, 7 | $puppetgem = $zabbix::params::puppetgem, 8 | ) inherits zabbix::params { 9 | # Determine correct zabbixapi version. 10 | case $zabbix_version { 11 | /^[56]\.[024]/: { 12 | $zabbixapi_version = '5.0.0-alpha1' 13 | if versioncmp($facts['ruby']['version'] , '3') < 0 { 14 | package { 'public_suffix': 15 | ensure => '5.1.1', 16 | provider => $puppetgem, 17 | } 18 | Package['public_suffix'] -> Package['zabbixapi'] 19 | } 20 | } 21 | default: { 22 | fail("Zabbix ${zabbix_version} is not supported!") 23 | } 24 | } 25 | 26 | $compile_packages = $facts['os']['family'] ? { 27 | 'RedHat' => ['make', 'gcc-c++', 'rubygems', 'ruby'], 28 | 'Debian' => ['make', 'g++', 'ruby-dev', 'ruby', 'pkg-config',], 29 | default => [], 30 | } 31 | ensure_packages($compile_packages) 32 | 33 | # Installing the zabbixapi gem package. We need this gem for 34 | # communicating with the zabbix-api. This is way better then 35 | # doing it ourself. 36 | package { 'zabbixapi': 37 | ensure => $zabbixapi_version, 38 | provider => $puppetgem, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /manifests/zapache.pp: -------------------------------------------------------------------------------- 1 | # @summary This will install and configure the zapache monitoring script Upstream: https://github.com/lorf/zapache 2 | # @param apache_status Boolean. False by default. Installs zapache monitoring script when true. 3 | # @example Basic installation: 4 | # class { 'zabbix::agent': 5 | # manage_resources => true, 6 | # apache_status => true, 7 | # zbx_templates => [ 'Template App Apache Web Server zapache'], 8 | # } 9 | # @author Robert Tisdale 10 | class zabbix::zapache ( 11 | Boolean $apache_status = $zabbix::params::apache_status, 12 | ) inherits zabbix::params { 13 | if $apache_status { 14 | file { ['/var/lib/zabbixsrv/','/var/lib/zabbixsrv/externalscripts/']: 15 | ensure => directory, 16 | owner => 'root', 17 | group => 'root', 18 | mode => '0755', 19 | } 20 | file { '/var/lib/zabbixsrv/externalscripts/zapache': 21 | ensure => file, 22 | source => 'puppet:///modules/zabbix/zapache/zapache', 23 | owner => 'root', 24 | group => 'root', 25 | mode => '0755', 26 | } 27 | file { '/etc/zabbix/zabbix_agentd.d/userparameter_zapache.conf': 28 | ensure => file, 29 | source => 'puppet:///modules/zabbix/zapache/userparameter_zapache.conf.sample', 30 | owner => 'root', 31 | group => 'root', 32 | mode => '0644', 33 | require => Package['zabbix-agent'], 34 | notify => Service['zabbix-agent'], 35 | } 36 | file { '/etc/httpd/conf.d/httpd-server-status.conf': 37 | ensure => file, 38 | source => 'puppet:///modules/zabbix/zapache/httpd-server-status.conf.sample', 39 | owner => 'root', 40 | group => 'root', 41 | mode => '0644', 42 | require => [Package['zabbix-agent'],Package['httpd']], 43 | notify => Service['httpd'], 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-zabbix", 3 | "version": "11.0.1-rc0", 4 | "summary": "Installing and maintaining Zabbix. Will install server, proxy, java-gateway and agent on RedHat/Debian/Ubuntu (Incl. exported resources).", 5 | "author": "Vox Pupuli", 6 | "dependencies": [ 7 | { 8 | "name": "puppetlabs/postgresql", 9 | "version_requirement": ">= 6.4.0 < 11.0.0" 10 | }, 11 | { 12 | "name": "puppetlabs/stdlib", 13 | "version_requirement": ">= 4.25.0 < 10.0.0" 14 | }, 15 | { 16 | "name": "puppetlabs/mysql", 17 | "version_requirement": ">= 6.0.0 < 17.0.0" 18 | }, 19 | { 20 | "name": "puppetlabs/apache", 21 | "version_requirement": ">= 9.0.0 < 13.0.0" 22 | }, 23 | { 24 | "name": "puppetlabs/firewall", 25 | "version_requirement": ">= 7.0.0 < 9.0.0" 26 | }, 27 | { 28 | "name": "puppetlabs/apt", 29 | "version_requirement": ">= 2.1.0 < 11.0.0" 30 | }, 31 | { 32 | "name": "puppet/systemd", 33 | "version_requirement": ">= 3.1.0 < 9.0.0" 34 | }, 35 | { 36 | "name": "puppet/selinux", 37 | "version_requirement": ">= 1.1.0 < 6.0.0" 38 | } 39 | ], 40 | "source": "https://github.com/voxpupuli/puppet-zabbix.git", 41 | "project_page": "https://github.com/voxpupuli/puppet-zabbix", 42 | "issues_url": "https://github.com/voxpupuli/puppet-zabbix/issues", 43 | "license": "Apache-2.0", 44 | "tags": [ 45 | "zabbix", 46 | "zabbix-server", 47 | "zabbix-proxy", 48 | "zabbix-agent", 49 | "zabbix-javagateway", 50 | "monitoring" 51 | ], 52 | "requirements": [ 53 | { 54 | "name": "openvox", 55 | "version_requirement": ">= 8.19.0 < 9.0.0" 56 | } 57 | ], 58 | "operatingsystem_support": [ 59 | { 60 | "operatingsystem": "RedHat", 61 | "operatingsystemrelease": [ 62 | "8", 63 | "9" 64 | ] 65 | }, 66 | { 67 | "operatingsystem": "OracleLinux", 68 | "operatingsystemrelease": [ 69 | "8", 70 | "9" 71 | ] 72 | }, 73 | { 74 | "operatingsystem": "CentOS", 75 | "operatingsystemrelease": [ 76 | "9" 77 | ] 78 | }, 79 | { 80 | "operatingsystem": "AlmaLinux", 81 | "operatingsystemrelease": [ 82 | "8", 83 | "9" 84 | ] 85 | }, 86 | { 87 | "operatingsystem": "Rocky", 88 | "operatingsystemrelease": [ 89 | "8", 90 | "9" 91 | ] 92 | }, 93 | { 94 | "operatingsystem": "Ubuntu", 95 | "operatingsystemrelease": [ 96 | "20.04", 97 | "22.04" 98 | ] 99 | }, 100 | { 101 | "operatingsystem": "Debian", 102 | "operatingsystemrelease": [ 103 | "11", 104 | "12" 105 | ] 106 | }, 107 | { 108 | "operatingsystem": "Archlinux" 109 | }, 110 | { 111 | "operatingsystem": "Gentoo" 112 | }, 113 | { 114 | "operatingsystem": "Raspbian", 115 | "operatingsystemrelease": [ 116 | "9", 117 | "10" 118 | ] 119 | }, 120 | { 121 | "operatingsystem": "windows", 122 | "operatingsystemrelease": [ 123 | "2016", 124 | "2019" 125 | ] 126 | }, 127 | { 128 | "operatingsystem": "AIX", 129 | "operatingsystemrelease": [ 130 | "7" 131 | ] 132 | }, 133 | { 134 | "operatingsystem": "FreeBSD", 135 | "operatingsystemrelease": [ 136 | "13" 137 | ] 138 | } 139 | ] 140 | } 141 | -------------------------------------------------------------------------------- /spec/acceptance/agent_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | supported_agent_versions(default[:platform]).each do |version| 6 | describe "zabbix::agent class with zabbix_version #{version}" do 7 | before(:all) do 8 | prepare_host 9 | end 10 | 11 | context 'With minimal parameter' do 12 | it_behaves_like 'an idempotent resource' do 13 | let(:manifest) do 14 | <<-PUPPET 15 | class { 'zabbix::agent': 16 | server => '192.168.20.11', 17 | zabbix_package_state => 'latest', 18 | zabbix_version => '#{version}', 19 | } 20 | PUPPET 21 | end 22 | end 23 | 24 | # do some basic checks 25 | describe package('zabbix-agent') do 26 | it { is_expected.to be_installed } 27 | end 28 | 29 | describe service('zabbix-agent') do 30 | it { is_expected.to be_running } 31 | it { is_expected.to be_enabled } 32 | end 33 | 34 | describe file('/etc/zabbix/zabbix_agentd.conf') do 35 | its(:content) { is_expected.not_to match %r{ListenIP=} } 36 | end 37 | end 38 | 39 | context 'With ListenIP set to an IP-Address' do 40 | it_behaves_like 'an idempotent resource' do 41 | let(:manifest) do 42 | <<-PUPPET 43 | class { 'zabbix::agent': 44 | server => '192.168.20.11', 45 | zabbix_package_state => 'latest', 46 | listenip => '127.0.0.1', 47 | zabbix_version => '#{version}', 48 | } 49 | PUPPET 50 | end 51 | end 52 | 53 | describe file('/etc/zabbix/zabbix_agentd.conf') do 54 | its(:content) { is_expected.to match %r{ListenIP=127.0.0.1} } 55 | end 56 | end 57 | 58 | context 'With ListenIP set to lo' do 59 | it_behaves_like 'an idempotent resource' do 60 | let(:manifest) do 61 | <<-PUPPET 62 | class { 'zabbix::agent': 63 | server => '192.168.20.11', 64 | zabbix_package_state => 'latest', 65 | listenip => 'lo', 66 | zabbix_version => '#{version}', 67 | } 68 | PUPPET 69 | end 70 | end 71 | 72 | describe file('/etc/zabbix/zabbix_agentd.conf') do 73 | its(:content) { is_expected.to match %r{ListenIP=127.0.0.1} } 74 | end 75 | end 76 | end 77 | 78 | describe "zabbix::agent class with agent2 and zabbix_version #{version}" do 79 | # <6.0 agent2 packages are not available for ubuntu 22.04 80 | next if version < '6.0' && default[:platform] =~ %r{ubuntu-22} 81 | 82 | before(:all) do 83 | prepare_host 84 | end 85 | 86 | context 'With minimal parameter' do 87 | it_behaves_like 'an idempotent resource' do 88 | let(:manifest) do 89 | <<-PUPPET 90 | class { 'zabbix::agent': 91 | agent_configfile_path => '/etc/zabbix/zabbix_agent2.conf', 92 | include_dir => '/etc/zabbix/zabbix_agent2.d', 93 | include_dir_purge => false, 94 | zabbix_package_agent => 'zabbix-agent2', 95 | servicename => 'zabbix-agent2', 96 | manage_startup_script => false, 97 | server => '192.168.20.11', 98 | zabbix_package_state => 'latest', 99 | zabbix_version => '#{version}', 100 | } 101 | PUPPET 102 | end 103 | end 104 | 105 | # do some basic checks 106 | describe package('zabbix-agent2') do 107 | it { is_expected.to be_installed } 108 | end 109 | 110 | describe service('zabbix-agent2') do 111 | it { is_expected.to be_running } 112 | it { is_expected.to be_enabled } 113 | end 114 | 115 | describe file('/etc/zabbix/zabbix_agentd2.conf') do 116 | its(:content) { is_expected.not_to match %r{ListenIP=} } 117 | end 118 | end 119 | 120 | context 'With ListenIP set to an IP-Address' do 121 | it_behaves_like 'an idempotent resource' do 122 | let(:manifest) do 123 | <<-PUPPET 124 | class { 'zabbix::agent': 125 | agent_configfile_path => '/etc/zabbix/zabbix_agent2.conf', 126 | include_dir => '/etc/zabbix/zabbix_agent2.d', 127 | include_dir_purge => false, 128 | zabbix_package_agent => 'zabbix-agent2', 129 | servicename => 'zabbix-agent2', 130 | manage_startup_script => false, 131 | server => '192.168.20.11', 132 | zabbix_package_state => 'latest', 133 | listenip => '127.0.0.1', 134 | zabbix_version => '#{version}', 135 | } 136 | PUPPET 137 | end 138 | end 139 | 140 | describe file('/etc/zabbix/zabbix_agent2.conf') do 141 | its(:content) { is_expected.to match %r{ListenIP=127.0.0.1} } 142 | end 143 | end 144 | 145 | context 'With ListenIP set to lo' do 146 | it_behaves_like 'an idempotent resource' do 147 | let(:manifest) do 148 | <<-PUPPET 149 | class { 'zabbix::agent': 150 | agent_configfile_path => '/etc/zabbix/zabbix_agent2.conf', 151 | include_dir => '/etc/zabbix/zabbix_agent2.d', 152 | include_dir_purge => false, 153 | zabbix_package_agent => 'zabbix-agent2', 154 | servicename => 'zabbix-agent2', 155 | manage_startup_script => false, 156 | server => '192.168.20.11', 157 | zabbix_package_state => 'latest', 158 | listenip => 'lo', 159 | zabbix_version => '#{version}', 160 | } 161 | PUPPET 162 | end 163 | 164 | describe file('/etc/zabbix/zabbix_agent2.conf') do 165 | its(:content) { is_expected.to match %r{ListenIP=127.0.0.1} } 166 | end 167 | end 168 | end 169 | end 170 | end 171 | -------------------------------------------------------------------------------- /spec/acceptance/hieradata/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apache::mpm_module: 'prefork' 3 | 4 | postgresql::globals::encoding: 'UTF-8' 5 | postgresql::globals::locale: 'en_US.UTF-8' 6 | postgresql::globals::manage_package_repo: true 7 | postgresql::globals::version: '13' 8 | # workaround for https://github.com/puppetlabs/puppetlabs-postgresql/issues/1572 9 | postgresql::server::service_status: systemctl status postgresql > /dev/null 10 | -------------------------------------------------------------------------------- /spec/acceptance/hieradata/family/RedHat/8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | postgresql::globals::manage_dnf_module: true 3 | postgresql::globals::manage_package_repo: false 4 | -------------------------------------------------------------------------------- /spec/acceptance/hieradata/family/RedHat/9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | postgresql::globals::manage_dnf_module: true 3 | postgresql::globals::manage_package_repo: false 4 | postgresql::globals::version: '15' -------------------------------------------------------------------------------- /spec/acceptance/server_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | describe 'zabbix::server class', unless: default[:platform] =~ %r{archlinux} do 5 | before(:all) do 6 | prepare_host 7 | end 8 | 9 | context 'default parameters' do 10 | it_behaves_like 'an idempotent resource' do 11 | # this is a minimal working example if you've a postgres server 12 | # running on another node. multinode testing with beaker is pain, 13 | # so we will deploy multiple services into one box 14 | # pp = <<-EOS 15 | # class { 'zabbix::server': 16 | # manage_database => false, 17 | # } 18 | # EOS 19 | 20 | # this will actually deploy apache + postgres + zabbix-server + zabbix-web 21 | let(:manifest) do 22 | <<-PUPPET 23 | class { 'zabbix::database': } 24 | -> class { 'zabbix::server': } 25 | PUPPET 26 | end 27 | end 28 | 29 | # do some basic checks 30 | describe package('zabbix-server-pgsql') do 31 | it { is_expected.to be_installed } 32 | end 33 | 34 | describe service('zabbix-server') do 35 | it { is_expected.to be_running } 36 | it { is_expected.to be_enabled } 37 | end 38 | end 39 | 40 | supported_server_versions(default[:platform]).each do |zabbix_version| 41 | context "deploys a zabbix #{zabbix_version} server" do 42 | it_behaves_like 'an idempotent resource' do 43 | # this is a minimal working example if you've a postgres server 44 | # running on another node. multinode testing with beaker is pain, 45 | # so we will deploy multiple services into one box 46 | # pp = <<-EOS 47 | # class { 'zabbix::server': 48 | # manage_database => false, 49 | # } 50 | # EOS 51 | # this will actually deploy apache + postgres + zabbix-server + zabbix-web 52 | let(:manifest) do 53 | <<-PUPPET 54 | class { 'zabbix::database': } 55 | -> class { 'zabbix::server': 56 | zabbix_version => "#{zabbix_version}" 57 | } 58 | PUPPET 59 | end 60 | end 61 | 62 | # do some basic checks 63 | describe package('zabbix-server-pgsql') do 64 | it { is_expected.to be_installed } 65 | end 66 | 67 | describe service('zabbix-server') do 68 | it { is_expected.to be_running } 69 | it { is_expected.to be_enabled } 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/acceptance/zabbix_hostgroup_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | require 'serverspec_type_zabbixapi' 5 | 6 | describe 'zabbix_hostgroup type' do 7 | supported_server_versions(default[:platform]).each do |zabbix_version| 8 | # Zabbix 7.0 removed the deprecated params 'user' in favor to 'username' 9 | next if zabbix_version >= '7.0' 10 | 11 | context "create zabbix_hostgroup resources with zabbix version #{zabbix_version}" do 12 | # This will deploy a running Zabbix setup (server, web, db) which we can 13 | # use for custom type tests 14 | pp1 = <<-EOS 15 | class { 'zabbix': 16 | zabbix_version => "#{zabbix_version}", 17 | zabbix_url => 'localhost', 18 | zabbix_api_user => 'Admin', 19 | zabbix_api_pass => 'zabbix', 20 | apache_use_ssl => false, 21 | manage_resources => true, 22 | } 23 | EOS 24 | 25 | pp2 = <<-EOS 26 | Zabbix_hostgroup { } 27 | 28 | zabbix_hostgroup { 'Testgroup2': } 29 | zabbix_hostgroup { 'Linux servers': 30 | ensure => absent, 31 | } 32 | EOS 33 | 34 | # setup zabbix. Apache module isn't idempotent and requires a second run 35 | it 'works with no error on the first apply' do 36 | # Cleanup old database 37 | prepare_host 38 | 39 | apply_manifest(pp1, catch_failures: true) 40 | end 41 | 42 | it 'works with no error on the second apply' do 43 | apply_manifest(pp1, catch_failures: true) 44 | end 45 | 46 | it 'works with no error on the third apply' do 47 | apply_manifest(pp2, catch_failures: true) 48 | end 49 | end 50 | 51 | let(:result_hostgroups) do 52 | zabbixapi('localhost', 'Admin', 'zabbix', 'hostgroup.get', output: 'extend').result 53 | end 54 | 55 | context 'Testgroup2' do 56 | it 'is created' do 57 | expect(result_hostgroups.map { |t| t['name'] }).to include('Testgroup2') 58 | end 59 | end 60 | 61 | context 'Linux servers' do 62 | it 'is absent' do 63 | expect(result_hostgroups.map { |t| t['name'] }).not_to include('Linux servers') 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /spec/acceptance/zabbix_proxy_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | require 'serverspec_type_zabbixapi' 5 | 6 | # rubocop:disable RSpec/LetBeforeExamples 7 | describe 'zabbix_proxy type' do 8 | supported_server_versions(default[:platform]).each do |zabbix_version| 9 | # Zabbix 7.0 removed the deprecated params 'user' in favor to 'username' 10 | next if zabbix_version >= '7.0' 11 | 12 | context "create zabbix_proxy resources with zabbix version #{zabbix_version}" do 13 | # This will deploy a running Zabbix setup (server, web, db) which we can 14 | # use for custom type tests 15 | pp1 = <<-EOS 16 | class { 'zabbix': 17 | zabbix_version => "#{zabbix_version}", 18 | zabbix_url => 'localhost', 19 | zabbix_api_user => 'Admin', 20 | zabbix_api_pass => 'zabbix', 21 | apache_use_ssl => false, 22 | manage_resources => true, 23 | } 24 | EOS 25 | 26 | # setup zabbix. Apache module isn't idempotent and requires a second run 27 | it 'works with no error on first apply' do 28 | # Cleanup old database 29 | prepare_host 30 | 31 | apply_manifest(pp1, catch_failures: true) 32 | end 33 | 34 | it 'works with no error on second apply' do 35 | apply_manifest(pp1, catch_failures: true) 36 | end 37 | 38 | # setup proxies within zabbix 39 | it_behaves_like 'an idempotent resource' do 40 | let(:manifest) do 41 | <<-PUPPET 42 | zabbix_proxy { 'ZabbixProxy1': 43 | mode => 0, 44 | } 45 | zabbix_proxy { 'ZabbixProxy2': 46 | ipaddress => '127.0.0.3', 47 | use_ip => false, 48 | mode => 1, 49 | port => 10055, 50 | } 51 | PUPPET 52 | end 53 | end 54 | 55 | let(:result_proxies) do 56 | zabbixapi('localhost', 'Admin', 'zabbix', 'proxy.get', selectInterface: %w[dns ip port useip], output: ['host']).result 57 | end 58 | 59 | context 'ZabbixProxy1' do 60 | let(:proxy1) { result_proxies.select { |h| h['host'] == 'ZabbixProxy1' }.first } 61 | 62 | it 'is created' do 63 | expect(proxy1['host']).to eq('ZabbixProxy1') 64 | end 65 | 66 | it 'has no interfaces configured' do 67 | # Active proxies do not have interface 68 | expect(proxy1['interface']).to eq([]) 69 | end 70 | end 71 | 72 | context 'ZabbixProxy2' do 73 | let(:proxy2) { result_proxies.select { |h| h['host'] == 'ZabbixProxy2' }.first } 74 | 75 | it 'is created' do 76 | expect(proxy2['host']).to eq('ZabbixProxy2') 77 | end 78 | 79 | it 'has a interfaces dns configured' do 80 | expect(proxy2['interface']['dns']).to eq('ZabbixProxy2') 81 | end 82 | 83 | it 'has a interfaces ip configured' do 84 | expect(proxy2['interface']['ip']).to eq('127.0.0.3') 85 | end 86 | 87 | it 'has a interfaces port configured' do 88 | expect(proxy2['interface']['port']).to eq('10055') 89 | end 90 | 91 | it 'has a interfaces useip configured' do 92 | expect(proxy2['interface']['useip']).to eq('0') 93 | end 94 | end 95 | end 96 | 97 | context 'update zabbix_proxy resources' do 98 | # This will update the Zabbix proxies created above by switching their configuration 99 | it_behaves_like 'an idempotent resource' do 100 | let(:manifest) do 101 | <<-PUPPET 102 | zabbix_proxy { 'ZabbixProxy1': 103 | ipaddress => '127.0.0.3', 104 | use_ip => false, 105 | mode => 1, 106 | port => 10055, 107 | } 108 | zabbix_proxy { 'ZabbixProxy2': 109 | mode => 0, 110 | } 111 | PUPPET 112 | end 113 | end 114 | 115 | let(:result_proxies) do 116 | zabbixapi('localhost', 'Admin', 'zabbix', 'proxy.get', selectInterface: %w[dns ip port useip], output: ['host']).result 117 | end 118 | 119 | context 'ZabbixProxy1' do 120 | let(:proxy1) { result_proxies.select { |h| h['host'] == 'ZabbixProxy1' }.first } 121 | 122 | it 'is created' do 123 | expect(proxy1['host']).to eq('ZabbixProxy1') 124 | end 125 | 126 | it 'has a interfaces dns configured' do 127 | expect(proxy1['interface']['dns']).to eq('ZabbixProxy1') 128 | end 129 | 130 | it 'has a interfaces ip configured' do 131 | expect(proxy1['interface']['ip']).to eq('127.0.0.3') 132 | end 133 | 134 | it 'has a interfaces port configured' do 135 | expect(proxy1['interface']['port']).to eq('10055') 136 | end 137 | 138 | it 'has a interfaces useip configured' do 139 | expect(proxy1['interface']['useip']).to eq('0') 140 | end 141 | end 142 | 143 | context 'ZabbixProxy2' do 144 | let(:proxy2) { result_proxies.select { |h| h['host'] == 'ZabbixProxy2' }.first } 145 | 146 | it 'is created' do 147 | expect(proxy2['host']).to eq('ZabbixProxy2') 148 | end 149 | 150 | it 'has no interfaces configured' do 151 | # Active proxies do not have interface 152 | expect(proxy2['interface']).to eq([]) 153 | end 154 | end 155 | end 156 | 157 | context 'delete zabbix_proxy resources' do 158 | # This will delete the Zabbix proxies create above 159 | it_behaves_like 'an idempotent resource' do 160 | let(:manifest) do 161 | <<-PUPPET 162 | zabbix_proxy { 'ZabbixProxy1': 163 | ensure => absent, 164 | } 165 | zabbix_proxy { 'ZabbixProxy2': 166 | ensure => absent, 167 | } 168 | PUPPET 169 | end 170 | end 171 | 172 | let(:result_proxies) do 173 | zabbixapi('localhost', 'Admin', 'zabbix', 'proxy.get', selectInterface: %w[dns ip port useip], output: ['host']).result 174 | end 175 | 176 | context 'ZabbixProxy1' do 177 | let(:proxy1) { result_proxies.select { |h| h['host'] == 'ZabbixProxy1' }.first } 178 | 179 | it "doesn't exist" do 180 | expect(proxy1).to eq(nil) 181 | end 182 | end 183 | 184 | context 'ZabbixProxy2' do 185 | let(:proxy2) { result_proxies.select { |h| h['host'] == 'ZabbixProxy2' }.first } 186 | 187 | it "doesn't exist" do 188 | expect(proxy2).to eq(nil) 189 | end 190 | end 191 | end 192 | end 193 | end 194 | -------------------------------------------------------------------------------- /spec/acceptance/zabbix_template_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | require 'serverspec_type_zabbixapi' 5 | 6 | describe 'zabbix_template type' do 7 | supported_server_versions(default[:platform]).each do |zabbix_version| 8 | # Zabbix 7.0 removed the deprecated params 'user' in favor to 'username' 9 | next if zabbix_version >= '7.0' 10 | 11 | context "create zabbix_template resources with zabbix version #{zabbix_version}" do 12 | # This will deploy a running Zabbix setup (server, web, db) which we can 13 | # use for custom type tests 14 | pp1 = <<-EOS 15 | class { 'zabbix': 16 | zabbix_version => "#{zabbix_version}", 17 | zabbix_url => 'localhost', 18 | zabbix_api_user => 'Admin', 19 | zabbix_api_pass => 'zabbix', 20 | apache_use_ssl => false, 21 | manage_resources => true, 22 | } 23 | EOS 24 | 25 | pp2 = <<-EOS 26 | zabbix_template { 'TestTemplate1': 27 | template_source => '/root/TestTemplate1.xml', 28 | zabbix_version => "#{zabbix_version}", 29 | } 30 | EOS 31 | 32 | shell("echo '4.02018-12-13T15:00:46ZTemplates/Applications' > /root/TestTemplate1.xml") 33 | 34 | # setup zabbix. Apache module isn't idempotent and requires a second run 35 | it 'works with no error on the first apply' do 36 | # Cleanup old database 37 | prepare_host 38 | 39 | apply_manifest(pp1, catch_failures: true) 40 | end 41 | 42 | it 'works with no error on the second apply' do 43 | apply_manifest(pp1, catch_failures: true) 44 | end 45 | 46 | it 'works with no error on the third apply' do 47 | apply_manifest(pp2, catch_failures: true) 48 | end 49 | end 50 | 51 | let(:result_templates) do 52 | # selectApplications parameter was removed in Zabbix 5.4 53 | if zabbix_version =~ %r{5\.[^4]} 54 | zabbixapi('localhost', 'Admin', 'zabbix', 'template.get', selectApplications: ['name'], output: ['host']).result 55 | else 56 | zabbixapi('localhost', 'Admin', 'zabbix', 'template.get', output: ['host']).result 57 | end 58 | end 59 | 60 | context 'TestTemplate1' do 61 | let(:template1) { result_templates.select { |t| t['host'] == 'TestTemplate1' }.first } 62 | 63 | it 'is created' do 64 | expect(template1['host']).to eq('TestTemplate1') 65 | end 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /spec/classes/database_mysql_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::database::mysql' do 6 | let :node do 7 | 'rspec.puppet.com' 8 | end 9 | 10 | on_supported_os.each do |os, facts| 11 | next if facts[:os]['name'] == 'windows' 12 | 13 | context "on #{os}" do 14 | let :facts do 15 | facts 16 | end 17 | 18 | context 'with all defaults' do 19 | it 'fails' do 20 | is_expected.not_to compile.with_all_deps 21 | end 22 | end 23 | 24 | supported_versions.each do |zabbix_version| 25 | # path to sql files on Debian and RedHat 26 | path = '/usr/share/zabbix-sql-scripts/mysql/' 27 | 28 | sql_server = 'server.sql' 29 | 30 | context "when zabbix_type is server and zabbix version is #{zabbix_version}" do 31 | describe 'and database_port is defined' do 32 | let :params do 33 | { 34 | database_name: 'zabbix-server', 35 | database_user: 'zabbix-server', 36 | database_password: 'zabbix-server', 37 | database_host: 'rspec.puppet.com', 38 | database_port: 3306, 39 | zabbix_type: 'server', 40 | zabbix_version: zabbix_version 41 | } 42 | end 43 | 44 | it { is_expected.to contain_class('zabbix::params') } 45 | it { is_expected.to contain_class('zabbix::database::mysql') } 46 | it { is_expected.to compile.with_all_deps } 47 | it { is_expected.to contain_exec('zabbix_server_create.sql').with_command("cd #{path} && if [ -f #{sql_server}.gz ]; then gunzip -f #{sql_server}.gz ; fi && mysql -h 'rspec.puppet.com' -u 'zabbix-server' -p'zabbix-server' -P 3306 -D 'zabbix-server' < #{sql_server} && touch /etc/zabbix/.schema.done") } 48 | end 49 | 50 | describe 'and no database_port is defined' do 51 | let :params do 52 | { 53 | database_name: 'zabbix-server', 54 | database_user: 'zabbix-server', 55 | database_password: 'zabbix-server', 56 | database_host: 'rspec.puppet.com', 57 | zabbix_type: 'server', 58 | zabbix_version: zabbix_version 59 | } 60 | end 61 | 62 | it { is_expected.to contain_class('zabbix::params') } 63 | it { is_expected.to contain_class('zabbix::database::mysql') } 64 | it { is_expected.to compile.with_all_deps } 65 | it { is_expected.to contain_exec('zabbix_server_create.sql').with_command("cd #{path} && if [ -f #{sql_server}.gz ]; then gunzip -f #{sql_server}.gz ; fi && mysql -h 'rspec.puppet.com' -u 'zabbix-server' -p'zabbix-server' -D 'zabbix-server' < #{sql_server} && touch /etc/zabbix/.schema.done") } 66 | end 67 | end 68 | 69 | context "when zabbix_type is proxy and zabbix version is #{zabbix_version}" do 70 | describe 'and database_port is defined' do 71 | let :params do 72 | { 73 | database_name: 'zabbix-proxy', 74 | database_user: 'zabbix-proxy', 75 | database_password: 'zabbix-proxy', 76 | database_host: 'rspec.puppet.com', 77 | database_port: 3306, 78 | zabbix_type: 'proxy', 79 | zabbix_version: zabbix_version 80 | } 81 | end 82 | 83 | it { is_expected.to contain_class('zabbix::params') } 84 | it { is_expected.to contain_class('zabbix::database::mysql') } 85 | it { is_expected.to compile.with_all_deps } 86 | it { is_expected.to contain_exec('zabbix_proxy_create.sql').with_command("cd #{path} && mysql -h 'rspec.puppet.com' -u 'zabbix-proxy' -p'zabbix-proxy' -P 3306 -D 'zabbix-proxy' < proxy.sql && touch /etc/zabbix/.schema.done") } 87 | end 88 | 89 | describe 'and no database_port is defined' do 90 | let :params do 91 | { 92 | database_name: 'zabbix-proxy', 93 | database_user: 'zabbix-proxy', 94 | database_password: 'zabbix-proxy', 95 | database_host: 'rspec.puppet.com', 96 | zabbix_type: 'proxy', 97 | zabbix_version: zabbix_version 98 | } 99 | end 100 | 101 | it { is_expected.to contain_class('zabbix::params') } 102 | it { is_expected.to contain_class('zabbix::database::mysql') } 103 | it { is_expected.to compile.with_all_deps } 104 | it { is_expected.to contain_exec('zabbix_proxy_create.sql').with_command("cd #{path} && mysql -h 'rspec.puppet.com' -u 'zabbix-proxy' -p'zabbix-proxy' -D 'zabbix-proxy' < proxy.sql && touch /etc/zabbix/.schema.done") } 105 | end 106 | end 107 | end 108 | end 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /spec/classes/database_postgresql_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::database::postgresql' do 6 | let :node do 7 | 'rspec.puppet.com' 8 | end 9 | 10 | on_supported_os.each do |os, facts| 11 | next if facts[:os]['name'] == 'windows' 12 | 13 | context "on #{os}" do 14 | let :facts do 15 | facts 16 | end 17 | 18 | let :params do 19 | { 20 | database_host: 'node01.example.com', 21 | } 22 | end 23 | 24 | let :expected_environment do 25 | [ 26 | 'PGHOST=node01.example.com', 27 | ] 28 | end 29 | 30 | supported_versions.each do |zabbix_version| 31 | path = '/usr/share/zabbix-sql-scripts/postgresql/' 32 | sql_server = 'server.sql' 33 | 34 | describe "when version is #{zabbix_version}" do 35 | let(:params) { super().merge(zabbix_version: zabbix_version) } 36 | 37 | describe 'when zabbix_type is server' do 38 | let(:params) do 39 | super().merge( 40 | database_name: 'zabbix-server', 41 | database_user: 'zabbix-server', 42 | database_password: 'zabbix-server', 43 | zabbix_type: 'server' 44 | ) 45 | end 46 | let(:expected_environment) do 47 | super() + [ 48 | 'PGPORT=5432', 49 | 'PGUSER=zabbix-server', 50 | 'PGPASSWORD=zabbix-server', 51 | 'PGDATABASE=zabbix-server', 52 | ] 53 | end 54 | 55 | it { is_expected.to compile.with_all_deps } 56 | it { is_expected.to contain_exec('zabbix_create.sql').with_command("cd #{path} && if [ -f #{sql_server}.gz ]; then zcat #{sql_server}.gz | psql ; else psql -f #{sql_server}; fi && touch /etc/zabbix/.schema.done").with_environment(expected_environment) } 57 | it { is_expected.to contain_class('zabbix::params') } 58 | 59 | describe 'with custom port is defined' do 60 | let(:params) { super().merge(database_port: 6432) } 61 | 62 | it { is_expected.to compile.with_all_deps } 63 | it { is_expected.to contain_exec('zabbix_create.sql').with_environment(expected_environment.map { |v| v.start_with?('PGPORT=') ? 'PGPORT=6432' : v }) } 64 | it { is_expected.to contain_class('zabbix::params') } 65 | end 66 | end 67 | 68 | describe 'when zabbix_type is proxy' do 69 | let :params do 70 | super().merge( 71 | database_name: 'zabbix-proxy', 72 | database_user: 'zabbix-proxy', 73 | database_password: 'zabbix-proxy', 74 | zabbix_type: 'proxy' 75 | ) 76 | end 77 | let(:expected_environment) do 78 | super() + [ 79 | 'PGPORT=5432', 80 | 'PGUSER=zabbix-proxy', 81 | 'PGPASSWORD=zabbix-proxy', 82 | 'PGDATABASE=zabbix-proxy', 83 | ] 84 | end 85 | 86 | it { is_expected.to compile.with_all_deps } 87 | 88 | it { is_expected.to contain_exec('zabbix_create.sql').with_command("cd #{path} && if [ -f proxy.sql.gz ]; then zcat proxy.sql.gz | psql ; else psql -f proxy.sql; fi && touch /etc/zabbix/.schema.done").with_environment(expected_environment) } 89 | it { is_expected.to contain_class('zabbix::params') } 90 | 91 | describe 'with a custom port' do 92 | let(:params) { super().merge(database_port: 6432) } 93 | 94 | it { is_expected.to compile.with_all_deps } 95 | it { is_expected.to contain_exec('zabbix_create.sql').with_environment(expected_environment.map { |v| v.start_with?('PGPORT=') ? 'PGPORT=6432' : v }) } 96 | it { is_expected.to contain_class('zabbix::params') } 97 | end 98 | end 99 | end 100 | end 101 | end 102 | end 103 | end 104 | -------------------------------------------------------------------------------- /spec/classes/javagateway_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::javagateway' do 6 | let :node do 7 | 'rspec.puppet.com' 8 | end 9 | 10 | on_supported_os.each do |os, facts| 11 | next if facts[:os]['name'] == 'windows' 12 | 13 | context "on #{os}" do 14 | let :facts do 15 | facts 16 | end 17 | 18 | context 'with all defaults' do 19 | it { is_expected.to contain_file('/etc/zabbix/zabbix_java_gateway.conf') } 20 | it { is_expected.to contain_service('zabbix-java-gateway') } 21 | it { is_expected.to contain_package('zabbix-java-gateway') } 22 | it { is_expected.to compile.with_all_deps } 23 | it { is_expected.to contain_class('zabbix::javagateway') } 24 | it { is_expected.to contain_class('zabbix::params') } 25 | 26 | it { is_expected.to contain_service('zabbix-java-gateway').with_ensure('running') } 27 | it { is_expected.to contain_service('zabbix-java-gateway').with_enable('true') } 28 | it { is_expected.to contain_service('zabbix-java-gateway').with_require(['Package[zabbix-java-gateway]', 'File[/etc/zabbix/zabbix_java_gateway.conf]']) } 29 | 30 | it { is_expected.to contain_apt__key('zabbix-A1848F5') } if facts[:os]['family'] == 'Debian' 31 | it { is_expected.to contain_apt__key('zabbix-FBABD5F') } if facts[:os]['family'] == 'Debian' 32 | end 33 | 34 | context 'when declaring manage_repo is true' do 35 | let :params do 36 | { 37 | manage_repo: true 38 | } 39 | end 40 | 41 | case facts[:os]['family'] 42 | when 'Archlinux' 43 | it { is_expected.not_to compile } 44 | when 'RedHat' 45 | # rubocop:disable RSpec/RepeatedExample 46 | it { is_expected.to contain_yumrepo('zabbix-nonsupported') } 47 | it { is_expected.to contain_yumrepo('zabbix') } 48 | it { is_expected.to contain_class('Zabbix::Repo') } 49 | when 'Debian' 50 | it { is_expected.to contain_apt__source('zabbix') } 51 | it { is_expected.to contain_class('Zabbix::Repo') } 52 | it { is_expected.to contain_class('apt') } 53 | # rubocop:enable RSpec/RepeatedExample 54 | end 55 | end 56 | 57 | context 'when declaring manage_firewall is true' do 58 | let(:params) do 59 | { 60 | manage_firewall: true 61 | } 62 | end 63 | 64 | it { is_expected.to contain_firewall('152 zabbix-javagateway') } 65 | end 66 | 67 | context 'when declaring manage_firewall is false' do 68 | let(:params) do 69 | { 70 | manage_firewall: false 71 | } 72 | end 73 | 74 | it { is_expected.not_to contain_firewall('152 zabbix-javagateway') } 75 | end 76 | 77 | context 'with zabbix_java_gateway.conf settings' do 78 | let(:params) do 79 | { 80 | listenip: '192.168.1.1', 81 | listenport: '10052', 82 | pidfile: '/var/run/zabbix/zabbix_java.pid', 83 | startpollers: '5', 84 | timeout: '15' 85 | } 86 | end 87 | 88 | it { is_expected.to contain_file('/etc/zabbix/zabbix_java_gateway.conf').with_content %r{^LISTEN_IP=192.168.1.1$} } 89 | it { is_expected.to contain_file('/etc/zabbix/zabbix_java_gateway.conf').with_content %r{^LISTEN_PORT=10052$} } 90 | it { is_expected.to contain_file('/etc/zabbix/zabbix_java_gateway.conf').with_content %r{^PID_FILE=/var/run/zabbix/zabbix_java.pid$} } 91 | it { is_expected.to contain_file('/etc/zabbix/zabbix_java_gateway.conf').with_content %r{^START_POLLERS=5$} } 92 | it { is_expected.to contain_file('/etc/zabbix/zabbix_java_gateway.conf').with_content %r{^TIMEOUT=15$} } 93 | end 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /spec/classes/repo_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'deep_merge' 4 | require 'spec_helper' 5 | 6 | describe 'zabbix::repo' do 7 | on_supported_os.each do |os, facts| 8 | context "on #{os}" do 9 | let :facts do 10 | facts 11 | end 12 | 13 | case facts[:os]['family'] 14 | when 'Archlinux', 'FreeBSD', 'Gentoo', 'AIX' 15 | # rubocop:disable RSpec/RepeatedExample 16 | it { is_expected.to compile.with_all_deps } 17 | when 'Debian' 18 | 19 | it { is_expected.to compile.with_all_deps } 20 | it { is_expected.to contain_class('zabbix::params') } 21 | it { is_expected.to contain_class('zabbix::repo') } 22 | 23 | it { is_expected.to contain_apt__key('zabbix-A1848F5') } if facts[:os]['family'] == 'Debian' 24 | it { is_expected.to contain_apt__key('zabbix-FBABD5F') } if facts[:os]['family'] == 'Debian' 25 | 26 | context 'when repo_location is "https://example.com/foo"' do 27 | let :params do 28 | { 29 | repo_location: 'https://example.com/foo' 30 | } 31 | end 32 | 33 | it { is_expected.to contain_apt__source('zabbix').with_location('https://example.com/foo') } 34 | end 35 | 36 | %w[arm64 aarch64].each do |arch| 37 | context "on #{arch}" do 38 | let :facts do 39 | facts.deep_merge(os: { architecture: arch }) 40 | end 41 | 42 | it { is_expected.to contain_apt__source('zabbix').with_location("http://repo.zabbix.com/zabbix/6.0/#{facts[:os]['name'].downcase}-arm64/") } 43 | end 44 | end 45 | when 'RedHat' 46 | 47 | it { is_expected.to compile.with_all_deps } 48 | it { is_expected.to contain_class('zabbix::params') } 49 | it { is_expected.to contain_class('zabbix::repo') } 50 | # rubocop:enable RSpec/RepeatedExample 51 | 52 | context 'when repo_location is "https://example.com/foo"' do 53 | let :params do 54 | { 55 | repo_location: 'https://example.com/foo' 56 | } 57 | end 58 | 59 | it { is_expected.to contain_yumrepo('zabbix').with_baseurl('https://example.com/foo') } 60 | end 61 | 62 | context 'when repo_gpg_key_location is "https://example.com/bar"' do 63 | let :params do 64 | { 65 | repo_gpg_key_location: 'https://example.com/bar' 66 | } 67 | end 68 | 69 | it { is_expected.to contain_yumrepo('zabbix').with_gpgkey('https://example.com/bar/RPM-GPG-KEY-ZABBIX-A14FE591') } if facts[:os]['release']['major'].to_i < 9 70 | it { is_expected.to contain_yumrepo('zabbix').with_gpgkey('https://example.com/bar/RPM-GPG-KEY-ZABBIX-08EFA7DD') } if facts[:os]['release']['major'].to_i >= 9 71 | end 72 | 73 | context 'when unsupported_repo_location is "https://example.com/foo"' do 74 | let :params do 75 | { 76 | unsupported_repo_location: 'https://example.com/foo' 77 | } 78 | end 79 | 80 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_baseurl('https://example.com/foo') } 81 | end 82 | 83 | context 'when unsupported_repo_gpg_key_location is "https://example.com/bar"' do 84 | let :params do 85 | { 86 | unsupported_repo_gpg_key_location: 'https://example.com/bar' 87 | } 88 | end 89 | 90 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_gpgkey('https://example.com/bar/RPM-GPG-KEY-ZABBIX-79EA5ED4') } if facts[:os]['release']['major'].to_i < 9 91 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_gpgkey('https://example.com/bar/RPM-GPG-KEY-ZABBIX-08EFA7DD') } if facts[:os]['release']['major'].to_i >= 9 92 | end 93 | 94 | major = facts[:os]['release']['major'] 95 | 96 | context "on RedHat #{major} and Zabbix 6.0" do 97 | let :params do 98 | { 99 | zabbix_version: '6.0', 100 | manage_repo: true 101 | } 102 | end 103 | 104 | it { is_expected.to contain_yumrepo('zabbix').with_baseurl("https://repo.zabbix.com/zabbix/6.0/rhel/#{major}/$basearch/") } 105 | 106 | it { is_expected.to contain_yumrepo('zabbix').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-A14FE591') } if facts[:os]['release']['major'].to_i < 9 107 | it { is_expected.to contain_yumrepo('zabbix').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-08EFA7DD') } if facts[:os]['release']['major'].to_i >= 9 108 | 109 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_baseurl("https://repo.zabbix.com/non-supported/rhel/#{major}/$basearch/") } 110 | 111 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-79EA5ED4') } if facts[:os]['release']['major'].to_i < 9 112 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-08EFA7DD') } if facts[:os]['release']['major'].to_i >= 9 113 | end 114 | 115 | context "on RedHat #{major} and Zabbix 7.0" do 116 | let :params do 117 | { 118 | zabbix_version: '7.0', 119 | manage_repo: true 120 | } 121 | end 122 | 123 | it { is_expected.to contain_yumrepo('zabbix').with_baseurl("https://repo.zabbix.com/zabbix/7.0/rhel/#{major}/$basearch/") } 124 | it { is_expected.to contain_yumrepo('zabbix').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-B5333005') } 125 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_baseurl("https://repo.zabbix.com/non-supported/rhel/#{major}/$basearch/") } 126 | 127 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-B5333005') } if facts[:os]['release']['major'].to_i < 9 128 | it { is_expected.to contain_yumrepo('zabbix-nonsupported').with_gpgkey('https://repo.zabbix.com/RPM-GPG-KEY-ZABBIX-08EFA7DD') } if facts[:os]['release']['major'].to_i >= 9 129 | end 130 | end 131 | end 132 | end 133 | end 134 | -------------------------------------------------------------------------------- /spec/classes/sender_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::sender' do 6 | let :node do 7 | 'agent.example.com' 8 | end 9 | 10 | on_supported_os.each do |os, facts| 11 | next if facts[:os]['name'] == 'windows' 12 | 13 | context "on #{os}" do 14 | let :facts do 15 | facts 16 | end 17 | 18 | zabbix_version = '6.0' 19 | 20 | context 'with all defaults' do 21 | it { is_expected.to contain_class('zabbix::sender') } 22 | it { is_expected.to contain_class('zabbix::params') } 23 | it { is_expected.to compile.with_all_deps } 24 | # Make sure package will be installed, service running and ensure of directory. 25 | it { is_expected.to contain_package('zabbix-sender').with_ensure('present') } 26 | it { is_expected.to contain_package('zabbix-sender').with_name('zabbix-sender') } 27 | end 28 | 29 | context 'when declaring manage_repo is true' do 30 | let :params do 31 | { 32 | manage_repo: true 33 | } 34 | end 35 | 36 | if %w[Archlinux Gentoo FreeBSD].include?(facts[:os]['family']) 37 | it { is_expected.not_to compile.with_all_deps } 38 | else 39 | it { is_expected.to contain_class('zabbix::repo').with_zabbix_version(zabbix_version) } 40 | it { is_expected.to contain_package('zabbix-sender').with_require('Class[Zabbix::Repo]') } 41 | end 42 | 43 | case facts[:os]['family'] 44 | when 'RedHat' 45 | it { is_expected.to contain_yumrepo('zabbix-nonsupported') } 46 | it { is_expected.to contain_yumrepo('zabbix') } 47 | when 'Debian' 48 | it { is_expected.to contain_apt__source('zabbix') } 49 | it { is_expected.to contain_apt__key('zabbix-A1848F5') } 50 | it { is_expected.to contain_apt__key('zabbix-FBABD5F') } 51 | end 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /spec/classes/userparameter_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::userparameter' do 6 | let :node do 7 | 'agent.example.com' 8 | end 9 | 10 | on_supported_os.each do |os, facts| 11 | context "on #{os}" do 12 | let :facts do 13 | facts 14 | end 15 | 16 | context 'with all defaults' do 17 | it { is_expected.to contain_class('zabbix::userparameter') } 18 | it { is_expected.to compile.with_all_deps } 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/defines/startup_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::startup', type: :define do # rubocop:disable RSpec/MultipleDescribes 6 | let(:title) { 'zabbix-agent' } 7 | let :pre_condition do 8 | 'service{"zabbix-agent":}' 9 | end 10 | 11 | on_supported_os.each do |os, os_facts| 12 | context "on #{os}" do 13 | context 'on legacy init systems' do 14 | ['false', false].each do |systemd_fact_state| 15 | let :facts do 16 | os_facts.merge({ systemd: systemd_fact_state }) 17 | end 18 | 19 | context 'it works' do 20 | let :params do 21 | { 22 | agent_configfile_path: '/something' 23 | } 24 | end 25 | 26 | case os_facts[:os]['family'] 27 | when 'Debian' 28 | it do 29 | is_expected.to contain_file('/etc/init.d/zabbix-agent').with( 30 | ensure: 'file', 31 | content: %r{DAEMON_OPTS="-c /something"} 32 | ) 33 | end 34 | when 'RedHat' 35 | it do 36 | is_expected.to contain_file('/etc/init.d/zabbix-agent').with( 37 | ensure: 'file', 38 | content: %r{OPTS="/something"} 39 | ) 40 | end 41 | when 'windows' 42 | it { is_expected.to have_exec_resource_count(1) } 43 | it { is_expected.to contain_exec('install_agent_zabbix-agent') } 44 | else 45 | it { is_expected.not_to compile.with_all_deps } 46 | 47 | next 48 | end 49 | it { is_expected.not_to contain_class('systemd') } 50 | it { is_expected.not_to contain_file('/etc/systemd/system/zabbix-agent.service') } 51 | end 52 | end 53 | end 54 | 55 | next if os_facts[:os]['family'] == 'windows' 56 | 57 | context "#{os} on systemd" do 58 | ['true', true].each do |systemd_fact_state| 59 | let :facts do 60 | os_facts.merge({ systemd: systemd_fact_state }) 61 | end 62 | 63 | context 'it works' do 64 | let :params do 65 | { 66 | agent_configfile_path: '/something', 67 | pidfile: '/somethingelse', 68 | additional_service_params: '--foreground' 69 | } 70 | end 71 | 72 | it { is_expected.to contain_class('systemd') } 73 | it { is_expected.to contain_systemd__unit_file('zabbix-agent.service') } 74 | it { is_expected.to contain_file('/etc/init.d/zabbix-agent').with_ensure('absent') } 75 | 76 | it do 77 | is_expected.to contain_file('/etc/systemd/system/zabbix-agent.service').with( 78 | ensure: 'file', 79 | mode: '0444' 80 | ) 81 | end 82 | 83 | it { is_expected.to contain_file('/etc/systemd/system/zabbix-agent.service').with_content(%r{ExecStart=/usr/sbin/zabbix_agentd --foreground -c /something}) } 84 | it { is_expected.to contain_file('/etc/systemd/system/zabbix-agent.service').with_content(%r{PIDFile=/somethingelse}) } 85 | end 86 | end 87 | end 88 | end 89 | end 90 | end 91 | 92 | describe 'zabbix::startup', type: :define do 93 | let(:title) { 'zabbix-server' } 94 | 95 | on_supported_os.each do |os, os_facts| 96 | context "on #{os}" do 97 | context 'on legacy init systems' do 98 | ['false', false].each do |systemd_fact_state| 99 | let :facts do 100 | os_facts.merge({ systemd: systemd_fact_state }) 101 | end 102 | 103 | context 'it works' do 104 | let :params do 105 | { 106 | server_configfile_path: '/something', 107 | database_type: 'mysql', 108 | manage_database: true 109 | } 110 | end 111 | 112 | case os_facts[:os]['family'] 113 | when 'Debian' 114 | it do 115 | is_expected.to contain_file('/etc/init.d/zabbix-server').with( 116 | ensure: 'file', 117 | content: %r{DAEMON_OPTS="-c /something"} 118 | ) 119 | end 120 | when 'RedHat' 121 | it do 122 | is_expected.to contain_file('/etc/init.d/zabbix-server').with( 123 | ensure: 'file', 124 | content: %r{OPTS="/something"} 125 | ) 126 | end 127 | else 128 | it { is_expected.not_to compile.with_all_deps } 129 | 130 | next 131 | end 132 | it { is_expected.not_to contain_class('systemd') } 133 | it { is_expected.not_to contain_file('/etc/systemd/system/zabbix-server.service') } 134 | end 135 | end 136 | end 137 | end 138 | 139 | next if os_facts[:os]['family'] == 'windows' 140 | 141 | context 'on systemd' do 142 | ['true', true].each do |systemd_fact_state| 143 | let :facts do 144 | os_facts.merge({ systemd: systemd_fact_state }) 145 | end 146 | 147 | context 'it works on mysql' do 148 | let :params do 149 | { 150 | server_configfile_path: '/something', 151 | pidfile: '/somethingelse', 152 | database_type: 'mysql', 153 | additional_service_params: '--foreground', 154 | manage_database: true 155 | } 156 | end 157 | 158 | it { is_expected.to contain_class('systemd') } 159 | it { is_expected.to contain_systemd__unit_file('zabbix-server.service') } 160 | it { is_expected.to contain_file('/etc/init.d/zabbix-server').with_ensure('absent') } 161 | 162 | it do 163 | is_expected.to contain_file('/etc/systemd/system/zabbix-server.service').with( 164 | ensure: 'file', 165 | mode: '0444' 166 | ) 167 | end 168 | 169 | it { is_expected.to contain_file('/etc/systemd/system/zabbix-server.service').with_content(%r{ExecStart=/usr/sbin/zabbix_server --foreground -c /something}) } 170 | it { is_expected.to contain_file('/etc/systemd/system/zabbix-server.service').with_content(%r{PIDFile=/somethingelse}) } 171 | it { is_expected.to contain_file('/etc/systemd/system/zabbix-server.service').with_content(%r{After=mysqld.service}) } 172 | 173 | context 'and works on postgres' do 174 | let :params do 175 | { 176 | server_configfile_path: '/something', 177 | pidfile: '/somethingelse', 178 | database_type: 'postgresql', 179 | manage_database: true 180 | } 181 | end 182 | 183 | it { is_expected.to contain_file('/etc/systemd/system/zabbix-server.service').with_content(%r{After=postgresql.service}) } 184 | end 185 | end 186 | end 187 | end 188 | end 189 | end 190 | -------------------------------------------------------------------------------- /spec/defines/userparameters_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix::userparameters', type: :define do 6 | on_supported_os.each do |os, facts| 7 | next if facts[:os]['name'] == 'windows' 8 | 9 | context "on #{os}" do 10 | let(:facts) { facts } 11 | let(:title) { 'mysqld' } 12 | let(:pre_condition) do 13 | 'class { "zabbix::agent": 14 | include_dir => "/etc/zabbix/zabbix_agentd.d", 15 | agent_configfile_path => "/etc/zabbix/zabbix_agentd.conf" 16 | }' 17 | end 18 | 19 | case facts[:os]['family'] 20 | when 'Gentoo' 21 | package_name = 'zabbix' 22 | service_name = 'zabbix-agentd' 23 | when 'FreeBSD' 24 | package_name = 'zabbix6-agent' 25 | service_name = 'zabbix_agentd' 26 | else 27 | package_name = 'zabbix-agent' 28 | service_name = 'zabbix-agent' 29 | end 30 | 31 | context 'with an content' do 32 | let(:params) { { content: 'UserParameter=mysql.ping,mysqladmin -uroot ping | grep -c alive' } } 33 | 34 | it { is_expected.to contain_file('/etc/zabbix/zabbix_agentd.d/mysqld.conf').with_ensure('present') } 35 | it { is_expected.to contain_file('/etc/zabbix/zabbix_agentd.d/mysqld.conf').with_content %r{^UserParameter=mysql.ping,mysqladmin -uroot ping | grep -c alive$} } 36 | it { is_expected.to contain_class('zabbix::params') } 37 | it { is_expected.to contain_class('zabbix::repo') } 38 | it { is_expected.to compile.with_all_deps } 39 | it { is_expected.not_to contain_file("/etc/init.d/#{service_name}") } 40 | it { is_expected.to contain_file('/etc/zabbix/zabbix_agentd.conf') } 41 | it { is_expected.to contain_file('/etc/zabbix/zabbix_agentd.d') } 42 | it { is_expected.to contain_package(package_name) } 43 | it { is_expected.to contain_service(service_name) } 44 | it { is_expected.not_to contain_zabbix__startup(service_name) } 45 | end 46 | 47 | context 'with ensure => absent' do 48 | let(:params) { { ensure: 'absent', content: 'UserParameter=mysql.ping,mysqladmin -uroot ping | grep -c alive' } } 49 | 50 | it { is_expected.to compile.with_all_deps } 51 | 52 | it { is_expected.to contain_file('/etc/zabbix/zabbix_agentd.d/mysqld.conf').with_ensure('absent') } 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/serverspec_type_zabbixapi.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | 5 | module Serverspec::Type 6 | class Zabbixapi < Base 7 | def initialize(host, user, pass, method, params) 8 | @name = 'zabbixapi' 9 | @host = host 10 | @user = user 11 | @pass = pass 12 | @method = method 13 | @params = params 14 | @runner = Specinfra::Runner 15 | @curl_base = "curl -s http://#{host}/api_jsonrpc.php -H \"Content-Type: application/json-rpc\" -d" 16 | 17 | @response = query(@method, @params) 18 | end 19 | 20 | def result 21 | @response['result'] 22 | end 23 | 24 | private 25 | 26 | def token 27 | @token ||= retrieve_token 28 | end 29 | 30 | def retrieve_token 31 | data = { 32 | jsonrpc: '2.0', 33 | method: 'user.login', 34 | params: { 35 | user: @user, 36 | password: @pass 37 | }, 38 | auth: nil, 39 | id: 0 40 | }.to_json 41 | do_request(data)['result'] 42 | end 43 | 44 | def query(method, params) 45 | data = { 46 | jsonrpc: '2.0', 47 | method: method, 48 | params: params, 49 | auth: token, 50 | id: 0 51 | }.to_json 52 | do_request(data) 53 | end 54 | 55 | def do_request(data) 56 | command = "#{@curl_base} '#{data}'" 57 | result = @runner.run_command(command) 58 | JSON.parse(result.stdout.chomp) 59 | end 60 | end 61 | 62 | def zabbixapi(host, user, pass, method, params) 63 | Zabbixapi.new(host, user, pass, method, params) 64 | end 65 | end 66 | include Serverspec::Type 67 | -------------------------------------------------------------------------------- /spec/setup_acceptance_node.pp: -------------------------------------------------------------------------------- 1 | case $facts['os']['name'] { 2 | 'Debian': { 3 | # On Debian it seems that make is searching for mkdir in /usr/bin/ but mkdir 4 | # does not exist. Symlink it from /bin/mkdir to make it work. 5 | if $facts['os']['release']['major'] < '12' { 6 | file { '/usr/bin/mkdir': 7 | ensure => link, 8 | target => '/bin/mkdir', 9 | } 10 | } 11 | package { 'gnupg': 12 | ensure => present, 13 | } 14 | } 15 | 'Ubuntu': { 16 | # The Ubuntu 18.04+ docker image has a dpkg config that won't install docs, to keep used space low 17 | # zabbix packages their SQL file as doc, we need that for bootstrapping the database 18 | file { '/etc/dpkg/dpkg.cfg.d/excludes': 19 | ensure => absent, 20 | } 21 | } 22 | default: {} 23 | } 24 | -------------------------------------------------------------------------------- /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 | end 15 | 16 | add_mocked_facts! 17 | 18 | if File.exist?(File.join(__dir__, 'default_module_facts.yml')) 19 | facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) 20 | facts&.each do |name, value| 21 | add_custom_fact name.to_sym, value 22 | end 23 | end 24 | 25 | require 'support/acceptance/supported_versions' 26 | Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f } 27 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'voxpupuli/acceptance/spec_helper_acceptance' 4 | 5 | configure_beaker 6 | 7 | Dir['./spec/support/acceptance/**/*.rb'].sort.each { |f| require f } 8 | -------------------------------------------------------------------------------- /spec/support/acceptance/prepare_host.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def prepare_host 4 | shell('yum clean all --verbose; rm -rf /etc/yum.repos.d/Zabbix*.repo') if fact('os.family') == 'RedHat' 5 | 6 | apply_manifest <<~PUPPET 7 | $services = $facts['os']['family'] ? { 8 | 'RedHat' => ['zabbix-server', 'httpd', 'zabbix-agentd', 'zabbix-agent', 'zabbix-agent2'], 9 | 'Debian' => ['zabbix-server', 'apache2', 'zabbix-agentd', 'zabbix-agent', 'zabbix-agent2'], 10 | default => ['zabbix-agentd', 'zabbix-agent', 'zabbix-agent2'], 11 | } 12 | service { $services: 13 | ensure => stopped 14 | } 15 | 16 | $packages = $facts['os']['family'] ? { 17 | 'RedHat' => ['zabbix-server-pgsql', 'zabbix-server-pgsql-scl', 'zabbix-web', 'zabbix-web-pgsql', 'zabbix-web-pgsql-scl', 'zabbix-frontend-php', 'zabbix-sql-scripts', 'zabbix-agent', 'zabbix-agent2'], 18 | 'Debian' => ['zabbix-server-pgsql', 'zabbix-web-pgsql', 'zabbix-frontend-php', 'zabbix-sql-scripts', 'zabbix-agent', 'zabbix-agent2'], 19 | default => ['zabbix-agent', 'zabbix-agent2'], 20 | } 21 | 22 | $pkg_ensure = $facts['os']['family'] ? { 23 | 'Archlinux' => absent, 24 | default => purged, 25 | } 26 | 27 | package { $packages: 28 | ensure => $pkg_ensure 29 | } 30 | PUPPET 31 | 32 | shell <<~SHELL 33 | /opt/puppetlabs/puppet/bin/gem uninstall zabbixapi -a 34 | rm -f /etc/zabbix/.*done 35 | if id postgres > /dev/null 2>&1; then 36 | su - postgres -c "psql -c 'drop database if exists zabbix_server;'" 37 | fi 38 | SHELL 39 | end 40 | -------------------------------------------------------------------------------- /spec/support/acceptance/supported_versions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def supported_versions 4 | supported_versions = %w[6.0 7.0] 5 | # this is a hack so that we don't have to rewrite the existing acceptance tests 6 | if (beaker_zabbix_version = ENV.fetch('BEAKER_FACTER_zabbix_version', nil)) 7 | supported_versions &= [beaker_zabbix_version] 8 | raise "Unsupported version: #{beaker_zabbix_version}" if supported_versions.empty? 9 | end 10 | supported_versions 11 | end 12 | 13 | def supported_agent_versions(platform) 14 | supported_versions.reject do |version| 15 | version < '6.0' && platform.start_with?('debian-12') 16 | end 17 | end 18 | 19 | def supported_server_versions(platform) 20 | supported_versions.reject do |version| 21 | platform.start_with?('archlinux') || 22 | (version < '6.0' && platform.start_with?('el-9', 'ubuntu-22', 'debian-12')) || 23 | (version >= '7.0' && platform.start_with?('ubuntu-20', 'debian-11')) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/types/zabbix_host_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'zabbix_host' do 6 | let(:title) { 'test1.example.com' } 7 | 8 | context 'with default provider' do 9 | it { is_expected.to be_valid_type.with_provider(:ruby) } 10 | 11 | it { is_expected.to be_valid_type.with_properties('ensure') } 12 | it { is_expected.to be_valid_type.with_properties('groups') } 13 | it { is_expected.to be_valid_type.with_properties('id') } 14 | it { is_expected.to be_valid_type.with_properties('interfaceid') } 15 | it { is_expected.to be_valid_type.with_properties('ipaddress') } 16 | it { is_expected.to be_valid_type.with_properties('port') } 17 | it { is_expected.to be_valid_type.with_properties('proxy') } 18 | it { is_expected.to be_valid_type.with_properties('templates') } 19 | it { is_expected.to be_valid_type.with_properties('macros') } 20 | it { is_expected.to be_valid_type.with_properties('use_ip') } 21 | 22 | it { is_expected.to be_valid_type.with_parameters('hostname') } 23 | it { is_expected.to be_valid_type.with_parameters('group_create') } 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/unit/puppet/provider/zabbix_host/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'fakefs/spec_helpers' 5 | 6 | describe Puppet::Type.type(:zabbix_host).provider(:ruby) do 7 | let(:resource) do 8 | Puppet::Type.type(:zabbix_host).new( 9 | hostname: 'test1.example.com' 10 | ) 11 | end 12 | let(:provider) { resource.provider } 13 | 14 | it 'be an instance of the correct provider' do 15 | expect(provider).to be_an_instance_of Puppet::Type::Zabbix_host::ProviderRuby 16 | end 17 | 18 | %i[instances prefetch].each do |method| 19 | it "responds to the class method #{method}" do 20 | expect(described_class).to respond_to(method) 21 | end 22 | end 23 | 24 | %i[create exists? destroy get_groupids get_templateids ipaddress use_ip port groups templates macros proxy].each do |method| 25 | it "responds to the instance method #{method}" do 26 | expect(described_class.new).to respond_to(method) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/unit/puppet/provider/zabbix_hostgroup/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:zabbix_hostgroup).provider(:ruby) do 6 | let(:resource) do 7 | Puppet::Type.type(:zabbix_hostgroup).new( 8 | name: 'Testgroup' 9 | ) 10 | end 11 | let(:provider) { resource.provider } 12 | 13 | it 'be an instance of the correct provider' do 14 | expect(provider).to be_an_instance_of Puppet::Type::Zabbix_hostgroup::ProviderRuby 15 | end 16 | 17 | %i[instances prefetch].each do |method| 18 | it "responds to the class method #{method}" do 19 | expect(described_class).to respond_to(method) 20 | end 21 | end 22 | 23 | %i[create exists? destroy].each do |method| 24 | it "responds to the instance method #{method}" do 25 | expect(described_class.new).to respond_to(method) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/unit/puppet/provider/zabbix_proxy/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:zabbix_proxy).provider(:ruby) do 6 | let(:resource) do 7 | Puppet::Type.type(:zabbix_proxy).new( 8 | name: 'Testproxy' 9 | ) 10 | end 11 | let(:provider) { resource.provider } 12 | 13 | it 'be an instance of the correct provider' do 14 | expect(provider).to be_an_instance_of Puppet::Type::Zabbix_proxy::ProviderRuby 15 | end 16 | 17 | %i[instances prefetch].each do |method| 18 | it "responds to the class method #{method}" do 19 | expect(described_class).to respond_to(method) 20 | end 21 | end 22 | 23 | %i[create exists? destroy].each do |method| 24 | it "responds to the instance method #{method}" do 25 | expect(described_class.new).to respond_to(method) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/unit/puppet/type/zabbix_host_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'unit/puppet/x/spec_zabbix_types' 5 | 6 | # rubocop:disable RSpec/LetBeforeExamples 7 | describe Puppet::Type.type(:zabbix_host) do 8 | describe 'when validating params' do 9 | %i[ 10 | group_create 11 | hostname 12 | ].each do |param| 13 | it "has a #{param} parameter" do 14 | expect(described_class.attrtype(param)).to eq(:param) 15 | end 16 | end 17 | end 18 | 19 | describe 'when validating properties' do 20 | %i[ 21 | groups 22 | id 23 | interfaceid 24 | ipaddress 25 | port 26 | proxy 27 | templates 28 | macros 29 | use_ip 30 | ].each do |param| 31 | it "has a #{param} property" do 32 | expect(described_class.attrtype(param)).to eq(:property) 33 | end 34 | end 35 | end 36 | 37 | describe 'munge_boolean' do 38 | { 39 | true => true, 40 | false => false, 41 | 'true' => true, 42 | 'false' => false, 43 | :true => true, 44 | :false => false 45 | }.each do |key, value| 46 | it "munges #{key.inspect} to #{value}" do 47 | expect(described_class.new(name: 'nobody').munge_boolean(key)).to eq value 48 | end 49 | end 50 | 51 | it 'fails on non boolean-ish values' do 52 | expect { described_class.new(name: 'nobody').munge_boolean('foo') }.to raise_error(Puppet::Error, 'munge_boolean only takes booleans') 53 | end 54 | end 55 | 56 | describe 'parameters' do 57 | describe 'hostname' do 58 | it_behaves_like 'generic namevar', :hostname 59 | end 60 | 61 | describe 'group_create' do 62 | it_behaves_like 'boolean parameter', :group_create, true 63 | 64 | { 'true' => true, 'false' => false, :true => true, :false => false }.each do |key, value| 65 | it "munge input value #{key.inspect} => #{value}" do 66 | object = described_class.new(name: 'nobody', group_create: key) 67 | expect(object[:group_create]).to eq(value) 68 | end 69 | end 70 | end 71 | end 72 | 73 | describe 'properties' do 74 | describe 'ensure' do 75 | it_behaves_like 'generic ensurable', :present 76 | end 77 | 78 | describe 'groups' do 79 | it_behaves_like 'array_matching property', :groups, nil 80 | 81 | let(:object) { described_class.new(name: 'nobody', groups: ['Group1', 'Group One']) } 82 | 83 | it 'ignores order of array' do 84 | expect(object.property(:groups).insync?(['Group One', 'Group1'])).to be true 85 | end 86 | end 87 | 88 | describe 'id' do 89 | it_behaves_like 'readonly property', :id 90 | end 91 | 92 | describe 'interfaceid' do 93 | it_behaves_like 'readonly property', :interfaceid 94 | end 95 | 96 | describe 'ipaddress' do 97 | it_behaves_like 'validated property', :ipaddress, nil, ['127.0.0.1', '10.0.1.2', 'fe80::21f:5133:f123:c23f/64'] 98 | end 99 | 100 | describe 'port' do 101 | it_behaves_like 'validated property', :port, nil, [10_050, '10050', 12_345] 102 | 103 | let(:object) { described_class.new(name: 'nobody', port: 40) } 104 | 105 | it 'ignores port received as string' do 106 | expect(object.property(:port).insync?('40')).to be true 107 | end 108 | end 109 | 110 | describe 'proxy' do 111 | it_behaves_like 'validated property', :proxy, nil, ['proxy1.example.com', 'proxy1'] 112 | end 113 | 114 | describe 'templates' do 115 | it_behaves_like 'validated property', :templates, nil, ['template1', 'Template One', ['template1', 'Template One']] 116 | it_behaves_like 'array_matching property', :templates 117 | 118 | let(:object) { described_class.new(name: 'nobody', templates: ['Template1', 'Template One']) } 119 | 120 | it 'ignores order of array' do 121 | expect(object.property(:templates).insync?(['Template One', 'Template1'])).to be true 122 | end 123 | end 124 | 125 | describe 'macros' do 126 | it_behaves_like 'validated property', :macros, nil, [{ 'macro1' => 'value1' }, { 'macro2' => 'value2' }] 127 | it_behaves_like 'array_matching property', :macros 128 | 129 | let(:object) { described_class.new(name: 'nobody', macros: [{ 'macro1' => 'value1' }, { 'macro2' => 'value2' }]) } 130 | 131 | it 'ignores order of array' do 132 | expect(object.property(:macros).insync?([{ 'macro1' => 'value1' }, { 'macro2' => 'value2' }])).to be true 133 | end 134 | end 135 | 136 | describe 'use_ip' do 137 | it_behaves_like 'boolean property', :use_ip, nil 138 | end 139 | end 140 | end 141 | -------------------------------------------------------------------------------- /spec/unit/puppet/type/zabbix_hostgroup_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:zabbix_hostgroup) do 6 | describe 'when validating attributes' do 7 | %i[name provider].each do |param| 8 | it "has a #{param} parameter" do 9 | expect(described_class.attrtype(param)).to eq(:param) 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/unit/puppet/type/zabbix_proxy_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:zabbix_proxy) do 6 | describe 'when validating params' do 7 | %i[ 8 | hostname 9 | provider 10 | ].each do |param| 11 | it "has a #{param} parameter" do 12 | expect(described_class.attrtype(param)).to eq(:param) 13 | end 14 | end 15 | end 16 | 17 | describe 'when validating properties' do 18 | %i[ 19 | ipaddress 20 | use_ip 21 | mode 22 | port 23 | ].each do |param| 24 | it "has a #{param} property" do 25 | expect(described_class.attrtype(param)).to eq(:property) 26 | end 27 | end 28 | end 29 | 30 | describe 'namevar' do 31 | it 'has :hostname as its namevar' do 32 | expect(described_class.key_attributes).to eq([:hostname]) 33 | end 34 | end 35 | 36 | describe 'port' do 37 | ['678', 573, 1, 65_535].each do |value| 38 | it "supports #{value} as a value to `port`" do 39 | expect { described_class.new(name: 'example_proxy', port: value) }.not_to raise_error 40 | end 41 | end 42 | ['foo', true, false, 1_000_000].each do |value| 43 | it "rejects #{value}" do 44 | expect { described_class.new(name: 'example_proxy', port: value) }.to raise_error(Puppet::Error, %r{invalid port}) 45 | end 46 | end 47 | end 48 | 49 | describe 'ipaddress' do 50 | ['127.0.0.1', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'].each do |value| 51 | it "supports #{value} as a value to `ipaddress`" do 52 | expect { described_class.new(name: 'example_proxy', ipaddress: value) }.not_to raise_error 53 | end 54 | end 55 | ['foo', true, false, 1_000_000, '192.463.0.1', '127.0.0.0.1'].each do |value| 56 | it "rejects #{value}" do 57 | expect { described_class.new(name: 'example_proxy', ipaddress: value) }.to raise_error(Puppet::Error, %r{Parameter ipaddress failed}) 58 | end 59 | end 60 | end 61 | 62 | describe 'mode' do 63 | describe 'munging' do 64 | ['0', 0, 'active'].each do |value| 65 | it "#{value} is munged to :active" do 66 | proxy = described_class.new(title: 'example_proxy', mode: value) 67 | expect(proxy[:mode]).to eq(:active) 68 | end 69 | end 70 | ['1', 1, 'passive'].each do |value| 71 | it "#{value} is munged to :passive" do 72 | proxy = described_class.new(title: 'example_proxy', mode: value) 73 | expect(proxy[:mode]).to eq(:passive) 74 | end 75 | end 76 | end 77 | end 78 | 79 | describe 'autorequiring' do 80 | let(:config_file) do 81 | Puppet::Type.type(:file).new(name: '/etc/zabbix/api.conf', ensure: :file) 82 | end 83 | let(:catalog) do 84 | Puppet::Resource::Catalog.new 85 | end 86 | let(:resource) do 87 | described_class.new(name: 'example_proxy') 88 | end 89 | let(:relationships) do 90 | resource.autorequire 91 | end 92 | 93 | before do 94 | catalog.add_resource config_file 95 | catalog.add_resource resource 96 | end 97 | 98 | it 'resource has one relationship' do 99 | expect(relationships.size).to eq(1) 100 | end 101 | 102 | it 'relationship target is the zabbix_proxy resource' do 103 | expect(relationships[0].target).to eq(resource) 104 | end 105 | 106 | it 'relationship source is the config file' do 107 | expect(relationships[0].source).to eq(config_file) 108 | end 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /spec/unit/puppet/type/zabbix_template_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'fakefs/spec_helpers' 5 | 6 | describe Puppet::Type.type(:zabbix_template) do 7 | let(:resource) do 8 | Puppet::Type.type(:zabbix_template).new( 9 | template_name: 'MyTemplate', 10 | template_source: '/path/to/template.xml' 11 | ) 12 | end 13 | let(:provider_class) { Puppet::Type.type(:zabbix_template).provider(:ruby) } 14 | let(:provider) { instance_double(provider_class, class: provider_class, clear: nil) } 15 | 16 | describe 'when validating attributes' do 17 | %i[ 18 | template_name 19 | template_source 20 | provider 21 | ].each do |param| 22 | it "has a #{param} parameter" do 23 | expect(described_class.attrtype(param)).to eq(:param) 24 | end 25 | end 26 | end 27 | 28 | describe 'namevar' do 29 | it 'has :template_name as its namevar' do 30 | expect(described_class.key_attributes).to eq([:template_name]) 31 | end 32 | end 33 | 34 | describe 'ensure' do 35 | let(:property) { resource.property(:ensure) } 36 | 37 | %i[present absent].each do |value| 38 | it "suppports #{value} as a value to :ensure" do 39 | expect { described_class.new(template_name: 'My template', ensure: value) }.not_to raise_error 40 | end 41 | end 42 | 43 | it 'rejects unknown values' do 44 | expect { described_class.new(template_name: 'My template', ensure: :foo) }.to raise_error(Puppet::Error) 45 | end 46 | 47 | it 'defaults to :present' do 48 | expect(described_class.new(name: 'My template').should(:ensure)).to eq(:present) 49 | end 50 | 51 | context 'when testing whether \'ensure\' is in sync' do 52 | it 'is insync if ensure is set to :present and the server template matches' do 53 | property.should = :present 54 | expect(property).to receive(:template_xmls_match?).and_return(true) 55 | expect(property).to be_safe_insync(:present) 56 | end 57 | 58 | it 'is not insync if ensure is set to :present but the source and server templates don\'t match' do 59 | property.should = :present 60 | expect(property).to receive(:template_xmls_match?).and_return(false) 61 | expect(property).not_to be_safe_insync(:present) 62 | end 63 | end 64 | 65 | describe '.template_xmls_match?' do 66 | mock_source_xml = <<-EOS 67 | 68 | 69 | 3.2 70 | 2016-11-29T09:27:09Z 71 | 72 | 73 | Templates 74 | 75 | 76 | 77 | 94 | 95 | 96 | EOS 97 | mock_provider_xml = <<-EOS 98 | 99 | 3.22016-11-30T12:06:25ZTemplates 100 | EOS 101 | it 'returns true when cleaned source xml matches cleaned server xml' do 102 | allow(provider_class).to receive(:new).and_return(provider) 103 | expect(property).to receive(:source_xml).and_return(mock_source_xml) 104 | expect(provider).to receive(:xml).and_return(mock_provider_xml) 105 | expect(property.template_xmls_match?).to eq true 106 | end 107 | end 108 | 109 | describe '.source_xml' do 110 | include FakeFS::SpecHelpers 111 | it 'returns content of :template_source as string' do 112 | mock_template_source_file = '/path/to/template.xml' 113 | mock_file_content = <<-EOS 114 | mock 115 | file 116 | content 117 | EOS 118 | FileUtils.mkdir_p '/path/to' 119 | File.write(mock_template_source_file, mock_file_content) 120 | expect(property.source_xml).to eq mock_file_content 121 | end 122 | end 123 | 124 | describe '.clean_xml' do 125 | it 'removes spaces after \'>\'s' do 126 | expect(property.clean_xml('> ')).to eq '>' 127 | end 128 | 129 | it 'removes tabs after \'>\'s' do 130 | expect(property.clean_xml(">\t")).to eq '>' 131 | end 132 | 133 | it 'removes newlines after \'>\'s' do 134 | expect(property.clean_xml(">\n")).to eq '>' 135 | end 136 | 137 | it 'removes spaces before \'<\'s' do 138 | expect(property.clean_xml(' <')).to eq '<' 139 | end 140 | 141 | it 'removes tabs before \'<\'s' do 142 | expect(property.clean_xml("\t<")).to eq '<' 143 | end 144 | 145 | it 'replaces dates with DATEWASHERE' do 146 | expect(property.clean_xml('2016-11-30T12:06:25Z')).to eq 'DATEWASHERE' 147 | end 148 | end 149 | 150 | describe '.change_to_s' do 151 | it 'returns \'Template updated\' when resource is being updated' do 152 | expect(property.change_to_s(:present, :present)).to eq 'Template updated' 153 | end 154 | 155 | it 'calls super otherwise' do 156 | expect(property.change_to_s(:absent, :present)).to eq 'created' 157 | end 158 | end 159 | end 160 | end 161 | -------------------------------------------------------------------------------- /spec/unit/puppet/x/spec_zabbix_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | shared_examples 'generic namevar' do |name| 6 | it { expect(described_class.attrtype(name)).to eq :param } 7 | 8 | it 'is the namevar' do 9 | expect(described_class.key_attributes).to eq [name] 10 | end 11 | end 12 | 13 | shared_examples 'generic ensurable' do |*allowed| 14 | allowed ||= [:present, :absent, 'present', 'absent'] 15 | 16 | context 'attrtype' do 17 | it { expect(described_class.attrtype(:ensure)).to eq :property } 18 | end 19 | 20 | context 'class' do 21 | it do 22 | expect(described_class.propertybyname(:ensure).ancestors). 23 | to include(Puppet::Property::Ensure) 24 | end 25 | end 26 | 27 | it 'defaults to :present' do 28 | expect(described_class.new(name: 'test').should(:ensure)).to eq(:present) 29 | end 30 | 31 | allowed.each do |value| 32 | it "supports #{value.inspect} as a value to :ensure" do 33 | expect { described_class.new(name: 'nobody', ensure: value) }.not_to raise_error 34 | end 35 | end 36 | 37 | it 'rejects unknown values' do 38 | expect { described_class.new(name: 'nobody', ensure: :foo) }.to raise_error(Puppet::Error) 39 | end 40 | end 41 | 42 | shared_examples 'boolean parameter' do |param, _default| 43 | it 'does not allow non-boolean values' do 44 | expect do 45 | described_class.new(:name => 'foo', param => 'unknown') 46 | end.to raise_error Puppet::ResourceError, %r{Valid values are true, false} 47 | end 48 | end 49 | 50 | shared_examples 'validated property' do |param, default, allowed, disallowed| 51 | context 'attrtype' do 52 | it { expect(described_class.attrtype(param)).to eq :property } 53 | end 54 | 55 | context 'allowed' do 56 | allowed.each do |value| 57 | it "supports #{value} as a value" do 58 | expect { described_class.new(:name => 'nobody', param => value) }. 59 | not_to raise_error 60 | end 61 | end 62 | end 63 | 64 | context 'disallowed' do 65 | disallowed&.each do |value| 66 | it "rejects #{value} as a value" do 67 | expect { described_class.new(:name => 'nobody', param => :value) }. 68 | to raise_error(Puppet::Error) 69 | end 70 | end 71 | end 72 | 73 | context 'default' do 74 | if default.nil? 75 | it 'has no default value' do 76 | resource = described_class.new(name: 'nobody') 77 | expect(resource.should(param)).to be_nil 78 | end 79 | else 80 | it "defaults to #{default}" do 81 | resource = described_class.new(name: 'nobody') 82 | expect(resource.should(param)).to eq default 83 | end 84 | end 85 | end 86 | end 87 | 88 | shared_examples 'array_matching property' do |param, default| 89 | context 'attrtype' do 90 | it { expect(described_class.attrtype(param)).to eq :property } 91 | end 92 | 93 | context 'array_matching' do 94 | it { expect(described_class.attrclass(param).array_matching).to eq :all } 95 | end 96 | 97 | it 'supports an array of mixed types' do 98 | value = [true, 'foo'] 99 | resource = described_class.new(name: 'test', param => value) 100 | expect(resource[param]).to eq value 101 | end 102 | 103 | context 'default' do 104 | if default.nil? 105 | it 'has no default value' do 106 | resource = described_class.new(name: 'nobody') 107 | expect(resource.should(param)).to be_nil 108 | end 109 | else 110 | it "defaults to #{default}" do 111 | resource = described_class.new(name: 'nobody') 112 | expect(resource.should(param)).to eq default 113 | end 114 | end 115 | end 116 | end 117 | 118 | shared_examples 'boolean property' do |param, default| 119 | it 'does not allow non-boolean values' do 120 | expect do 121 | described_class.new(:name => 'foo', param => 'unknown') 122 | end.to raise_error Puppet::ResourceError, %r{Invalid value "unknown". Valid values are true, false.} 123 | end 124 | 125 | it_behaves_like 'validated property', param, default, [true, false, 'true', 'false', :true, :false] 126 | end 127 | 128 | shared_examples 'readonly property' do |param| 129 | it 'is readonly' do 130 | expect do 131 | described_class.new(:name => 'foo', param => 'invalid') 132 | end.to raise_error(Puppet::Error, %r{#{param} is read-only}) 133 | end 134 | end 135 | -------------------------------------------------------------------------------- /templates/api.conf.epp: -------------------------------------------------------------------------------- 1 | <%- | String[1] $zabbix_url, 2 | String[1] $zabbix_user, 3 | String[1] $zabbix_pass, 4 | Boolean $apache_use_ssl, 5 | | -%> 6 | # MANAGED BY PUPPET 7 | [default] 8 | zabbix_url = <%= $zabbix_url %> 9 | zabbix_user = <%= $zabbix_user %> 10 | zabbix_pass = <%= $zabbix_pass %> 11 | apache_use_ssl = <%= $apache_use_ssl %> 12 | -------------------------------------------------------------------------------- /templates/selinux/zabbix-agent.te.erb: -------------------------------------------------------------------------------- 1 | module zabbix-agent 1.0; 2 | 3 | require { 4 | <% @selinux_require.each do |sel_require| -%> 5 | <%= sel_require %>; 6 | <% end -%> 7 | } 8 | 9 | <% @selinux_rules.keys.each do |key| -%> 10 | #============= <%= key %> ============== 11 | <% @selinux_rules[key].each do |rule| -%> 12 | <%= rule %>; 13 | <% end -%> 14 | 15 | <% end -%> 16 | -------------------------------------------------------------------------------- /templates/web/php-fpm.d.zabbix.conf.epp: -------------------------------------------------------------------------------- 1 | ;THIS FILE IS MANAGED BY PUPPET 2 | [zabbix] 3 | user = apache 4 | group = apache 5 | 6 | listen = /var/run/php-fpm/zabbix.sock 7 | listen.acl_users = apache 8 | listen.allowed_clients = 127.0.0.1 9 | 10 | pm = dynamic 11 | pm.max_children = 50 12 | pm.start_servers = 5 13 | pm.min_spare_servers = 5 14 | pm.max_spare_servers = 35 15 | 16 | php_value[session.save_handler] = files 17 | php_value[session.save_path] = /var/lib/php/session/ 18 | 19 | php_value[max_execution_time] = <%= $zabbix::web::apache_php_max_execution_time %> 20 | php_value[memory_limit] = <%= $zabbix::web::apache_php_memory_limit %> 21 | php_value[post_max_size] = <%= $zabbix::web::apache_php_post_max_size %> 22 | php_value[upload_max_filesize] = <%= $zabbix::web::apache_php_upload_max_filesize %> 23 | php_value[max_input_time] = <%= $zabbix::web::apache_php_max_input_time %> 24 | php_value[always_populate_raw_post_data] = <%= $zabbix::web::apache_php_always_populate_raw_post_data %> 25 | php_value[max_input_vars] = <%= $zabbix::web::apache_php_max_input_vars %> 26 | ;Set correct timezone 27 | php_value[date.timezone] = <%= $zabbix::web::zabbix_timezone %> 28 | -------------------------------------------------------------------------------- /templates/web/zabbix.conf.php.erb: -------------------------------------------------------------------------------- 1 | '; 6 | $DB['SERVER'] = '<%= @database_host %>'; 7 | <% if @database_port -%> 8 | $DB['PORT'] = '<%= @database_port %>'; 9 | <% elsif @db_port -%> 10 | $DB['PORT'] = '<%= @db_port %>'; 11 | <% else -%> 12 | $DB['PORT'] = '0'; 13 | <% end -%> 14 | $DB['DATABASE'] = '<%= @database_name %>'; 15 | $DB['USER'] = '<%= @database_user %>'; 16 | $DB['PASSWORD'] = '<%= @database_password %>'; 17 | 18 | // SCHEMA is relevant only for IBM_DB2 and PostgreSQL database 19 | <% if @database_schema -%> 20 | $DB['SCHEMA'] = '<%= @database_schema %>'; 21 | <% else -%> 22 | $DB['SCHEMA'] = ''; 23 | <% end -%> 24 | 25 | <% if @database_double_ieee754 -%> 26 | $DB['DOUBLE_IEEE754'] = 'true'; 27 | <% end -%> 28 | 29 | <% if @zabbix_version.to_f < 6.0 -%> 30 | $ZBX_SERVER = '<%= @zabbix_server %>'; 31 | $ZBX_SERVER_PORT = '<%= @zabbix_listenport %>'; 32 | <% end -%> 33 | $ZBX_SERVER_NAME = '<%= @zabbix_server_name %>'; 34 | 35 | $IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG; 36 | 37 | <% if @ldap_cacert %> 38 | putenv("LDAPTLS_CACERT=<%= @ldap_cacert %>"); 39 | <% end %> 40 | <% if @ldap_clientcert %> 41 | putenv("LDAPTLS_CERT=<%= @ldap_clientcert %>"); 42 | <% end %> 43 | <% if @ldap_clientkey %> 44 | putenv("LDAPTLS_KEY=<%= @ldap_clientkey %>"); 45 | <% end %> 46 | <% if @ldap_reqcert %> 47 | putenv("TLS_REQCERT=<%= @ldap_reqcert %>"); 48 | <% end %> 49 | 50 | <% if @saml_sp_key %> 51 | $SSO['SP_KEY'] = '<%= @saml_sp_key -%>'; 52 | <% end %> 53 | <% if @saml_sp_cert %> 54 | $SSO['SP_CERT'] = '<%= @saml_sp_cert -%>'; 55 | <% end %> 56 | <% if @saml_idp_cert %> 57 | $SSO['IDP_CERT'] = '<%= @saml_idp_cert -%>'; 58 | <% end %> 59 | <% if @saml_settings %> 60 | $SSO['SETTINGS'] = [ <%= JSON.pretty_generate(@saml_settings, space_before: " ") 61 | .sub("{", "") 62 | .gsub(" : ", " => ") 63 | .gsub("{", "[") 64 | .gsub("}", "]") -%>; 65 | <% end %> 66 | ?> 67 | -------------------------------------------------------------------------------- /templates/zabbix-agent-aix.init.epp: -------------------------------------------------------------------------------- 1 | <%- | String $pidfile, 2 | String $agent_configfile_path, 3 | String $zabbix_user 4 | | -%> 5 | #!/bin/ksh 6 | # THIS FILE IS MANAGED BY PUPPET 7 | 8 | 9 | ################################################## 10 | # name: start zabbix agent 11 | # purpose: zabbix agent start script 12 | # author: V.Danhelka IBM 11.2.2016; B. Schafer 2020-02-26 13 | ################################################## 14 | 15 | PID=<%= $pidfile %> 16 | BIN=/usr/sbin/zabbix_agentd 17 | CONF=<%= $agent_configfile_path %> 18 | LOGFILE=/var/log/zabbix/zabbix_agentd.log 19 | ARGS="-c $CONF" 20 | USER=<%= $zabbix_user %> 21 | 22 | test -d $(dirname $LOGFILE) || mkdir -p $(dirname $LOGFILE) 23 | chown -R $USER $LOGDIR 24 | 25 | test -d $(dirname $PID) || mkdir -p $(dirname $PID) 26 | chown -R $USER $(dirname $PID) 27 | 28 | case "$1" in 29 | start ) 30 | sudo -u $USER $BIN $ARGS 31 | ;; 32 | stop ) 33 | [ -f $PID ] && kill $(cat $PID) 34 | ;; 35 | restart ) 36 | [ -f $PID ] && kill $(cat $PID) 37 | sleep 5 38 | sudo -u $USER $BIN $ARGS 39 | ;; 40 | status) 41 | [ -f $PID ] && echo "running as $(cat $PID)" || echo "stopped" 42 | ;; 43 | * ) 44 | echo "Usage: $0 (start | stop | restart | status)" 45 | exit 1 46 | esac 47 | -------------------------------------------------------------------------------- /templates/zabbix-agent-debian.init.erb: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: zabbix-agent 4 | # Required-Start: $remote_fs $network 5 | # Required-Stop: $remote_fs 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # Short-Description: Start zabbix-agent daemon 9 | ### END INIT INFO 10 | 11 | set -e 12 | 13 | NAME=zabbix_agentd 14 | DAEMON=/usr/sbin/$NAME 15 | DAEMON_OPTS="-c <%= @agent_configfile_path %>" 16 | DESC="Zabbix agent" 17 | 18 | test -x $DAEMON || exit 0 19 | 20 | DIR=/var/run/zabbix 21 | PID=$DIR/$NAME.pid 22 | RETRY=15 23 | 24 | if test ! -d "$DIR"; then 25 | mkdir -p "$DIR" 26 | chown -R zabbix:zabbix "$DIR" 27 | fi 28 | 29 | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" 30 | 31 | # define LSB log_* functions. 32 | . /lib/lsb/init-functions 33 | 34 | if [ -r "/etc/default/zabbix-agent" ]; then 35 | . /etc/default/zabbix-agent 36 | fi 37 | 38 | case "$1" in 39 | start) 40 | log_daemon_msg "Starting $DESC" "$NAME" 41 | start-stop-daemon --oknodo --start --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS >/dev/null 2>&1 42 | case "$?" in 43 | 0) log_end_msg 0 ;; 44 | *) log_end_msg 1; exit 1 ;; 45 | esac 46 | ;; 47 | stop) 48 | log_daemon_msg "Stopping $DESC" "$NAME" 49 | start-stop-daemon --oknodo --stop --pidfile $PID --retry $RETRY 50 | case "$?" in 51 | 0) log_end_msg 0 ;; 52 | *) log_end_msg 1; exit 1 ;; 53 | esac 54 | ;; 55 | status) 56 | status_of_proc -p "$PID" "$DAEMON" "$NAME" && exit 0 || exit $? 57 | ;; 58 | restart|force-reload) 59 | $0 stop 60 | $0 start 61 | ;; 62 | *) 63 | echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 64 | exit 1 65 | ;; 66 | esac 67 | 68 | exit 0 69 | -------------------------------------------------------------------------------- /templates/zabbix-agent-redhat.init.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # /etc/rc.d/init.d/zabbix_agentd 4 | # 5 | # Starts the zabbix_agentd daemon 6 | # 7 | # chkconfig: - 95 5 8 | # description: Zabbix Monitoring Agent 9 | # processname: zabbix_agentd 10 | # pidfile: /tmp/zabbix_agentd.pid 11 | 12 | # Modified for Zabbix 2.0.0 13 | # May 2012, Zabbix SIA 14 | 15 | # Source function library. 16 | 17 | . /etc/init.d/functions 18 | 19 | RETVAL=0 20 | prog="Zabbix Agent" 21 | ZABBIX_BIN="$(type -P zabbix_agentd)" 22 | OPTS="<%= @agent_configfile_path %>" 23 | 24 | if [ ! -x ${ZABBIX_BIN} ] ; then 25 | echo -n "${ZABBIX_BIN} not installed! " 26 | # Tell the user this has skipped 27 | exit 5 28 | fi 29 | 30 | start() { 31 | echo -n $"Starting $prog: " 32 | daemon "$ZABBIX_BIN -c $OPTS" 33 | RETVAL=$? 34 | [ $RETVAL -eq 0 ] && touch /var/lock/subsys/zabbix_agentd 35 | echo 36 | } 37 | 38 | stop() { 39 | echo -n $"Stopping $prog: " 40 | killproc $ZABBIX_BIN 41 | RETVAL=$? 42 | [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/zabbix_agentd 43 | echo 44 | } 45 | 46 | case "$1" in 47 | start) 48 | start 49 | ;; 50 | stop) 51 | stop 52 | ;; 53 | reload|restart) 54 | stop 55 | sleep 10 56 | start 57 | RETVAL=$? 58 | ;; 59 | condrestart) 60 | if [ -f /var/lock/subsys/zabbix_agentd ]; then 61 | stop 62 | start 63 | fi 64 | ;; 65 | status) 66 | status $ZABBIX_BIN 67 | RETVAL=$? 68 | ;; 69 | *) 70 | echo $"Usage: $0 {condrestart|start|stop|restart|reload|status}" 71 | exit 1 72 | esac 73 | 74 | exit $RETVAL 75 | -------------------------------------------------------------------------------- /templates/zabbix-agent-systemd.init.erb: -------------------------------------------------------------------------------- 1 | # THIS FILE IS MANAGED BY PUPPET 2 | [Unit] 3 | Description=Zabbix Agent 4 | After=network.target 5 | 6 | [Service] 7 | <% if @service_type %>Type=<%= @service_type %><% end %> 8 | Restart=on-failure 9 | <% if @pidfile %>PIDFile=<%= @pidfile %><% end %> 10 | KillMode=control-group 11 | ExecStart=/usr/sbin/zabbix_agentd <%= @additional_service_params %> -c <%= @agent_configfile_path %> 12 | <% if @zabbix_user %>User=<%= @zabbix_user %><% end %> 13 | RestartSec=10s 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /templates/zabbix-server-debian.init.erb: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: zabbix-server 4 | # Required-Start: $remote_fs $network 5 | # Required-Stop: $remote_fs 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # Should-Start: mysql 9 | # Should-Stop: mysql 10 | # Short-Description: Start zabbix-server daemon 11 | ### END INIT INFO 12 | 13 | set -e 14 | 15 | NAME=zabbix_server 16 | DAEMON=/usr/sbin/$NAME 17 | DAEMON_OPTS="-c <%= @server_configfile_path %>" 18 | DESC="Zabbix server" 19 | 20 | test -x $DAEMON || exit 0 21 | 22 | DIR=/var/run/zabbix 23 | PID=$DIR/$NAME.pid 24 | RETRY=15 25 | 26 | if test ! -d "$DIR"; then 27 | mkdir -p "$DIR" 28 | chown -R zabbix:zabbix "$DIR" 29 | fi 30 | 31 | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" 32 | 33 | # define LSB log_* functions. 34 | . /lib/lsb/init-functions 35 | 36 | if [ -r "/etc/default/zabbix-server" ]; then 37 | . /etc/default/zabbix-server 38 | fi 39 | 40 | case "$1" in 41 | start) 42 | log_daemon_msg "Starting $DESC" "$NAME" 43 | start-stop-daemon --oknodo --start --pidfile $PID \ 44 | --exec $DAEMON -- $DAEMON_OPTS >/dev/null 2>&1 45 | case "$?" in 46 | 0) log_end_msg 0 ;; 47 | *) log_end_msg 1; exit 1 ;; 48 | esac 49 | ;; 50 | stop) 51 | log_daemon_msg "Stopping $DESC" "$NAME" 52 | start-stop-daemon --oknodo --stop --pidfile $PID --retry $RETRY 53 | case "$?" in 54 | 0) log_end_msg 0 ;; 55 | *) log_end_msg 1; exit 1 ;; 56 | esac 57 | ;; 58 | status) 59 | status_of_proc -p "$PID" "$DAEMON" "$NAME" && exit 0 || exit $? 60 | ;; 61 | restart|force-reload) 62 | $0 stop 63 | $0 start 64 | ;; 65 | *) 66 | echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 67 | exit 1 68 | ;; 69 | esac 70 | 71 | exit 0 72 | -------------------------------------------------------------------------------- /templates/zabbix-server-redhat.init.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # /etc/rc.d/init.d/zabbix_server 4 | # 5 | # Starts the zabbix_server daemon 6 | # 7 | # chkconfig: - 95 5 8 | # description: Zabbix Monitoring Server 9 | # processname: zabbix_server 10 | # pidfile: /tmp/zabbix_server.pid 11 | 12 | # Modified for Zabbix 2.0.0 13 | # May 2012, Zabbix SIA 14 | 15 | # Source function library. 16 | 17 | . /etc/init.d/functions 18 | 19 | RETVAL=0 20 | prog="Zabbix Server" 21 | ZABBIX_BIN="$(type -P zabbix_server)" 22 | OPTS="<%= @server_configfile_path %>" 23 | 24 | if [ ! -x ${ZABBIX_BIN} ] ; then 25 | echo -n "${ZABBIX_BIN} not installed! " 26 | # Tell the user this has skipped 27 | exit 5 28 | fi 29 | 30 | start() { 31 | echo -n $"Starting $prog: " 32 | daemon "$ZABBIX_BIN -c $OPTS" 33 | RETVAL=$? 34 | [ $RETVAL -eq 0 ] && touch /var/lock/subsys/zabbix_server 35 | echo 36 | } 37 | 38 | stop() { 39 | echo -n $"Stopping $prog: " 40 | killproc $ZABBIX_BIN 41 | RETVAL=$? 42 | [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/zabbix_server 43 | echo 44 | } 45 | 46 | case "$1" in 47 | start) 48 | start 49 | ;; 50 | stop) 51 | stop 52 | ;; 53 | reload|restart) 54 | stop 55 | sleep 10 56 | start 57 | RETVAL=$? 58 | ;; 59 | condrestart) 60 | if [ -f /var/lock/subsys/zabbix_server ]; then 61 | stop 62 | start 63 | fi 64 | ;; 65 | status) 66 | status $ZABBIX_BIN 67 | RETVAL=$? 68 | ;; 69 | *) 70 | echo $"Usage: $0 {condrestart|start|stop|restart|reload|status}" 71 | exit 1 72 | esac 73 | 74 | exit $RETVAL 75 | -------------------------------------------------------------------------------- /templates/zabbix-server-systemd.init.erb: -------------------------------------------------------------------------------- 1 | # THIS FILE IS MANAGED BY PUPPET 2 | [Unit] 3 | Description=Zabbix Server 4 | Documentation=man:zabbix_server 5 | <% if @database_type == "mysql" and @manage_database %> 6 | After=mysqld.service 7 | <% elsif @database_type == "postgresql" and @manage_database %> 8 | After=postgresql.service 9 | <% end -%> 10 | # Wait for network-online and not just network: 11 | # - Required in case of a remote database. 12 | # - Avoids missing data at boot on all network-based checks. 13 | After=network-online.target 14 | 15 | [Service] 16 | ExecStart=/usr/sbin/zabbix_server <%= @additional_service_params %> -c <%= @server_configfile_path %> 17 | ExecReload=/usr/sbin/zabbix_server -R config_cache_reload 18 | <% if @pidfile %>PIDFile=<%= @pidfile %><% end %> 19 | Restart=on-abnormal 20 | PrivateTmp=yes 21 | ProtectSystem=full 22 | ProtectHome=yes 23 | <% if @zabbix_user %>User=<%= @zabbix_user %><% end %> 24 | 25 | [Install] 26 | WantedBy=multi-user.target 27 | -------------------------------------------------------------------------------- /templates/zabbix_java_gateway.conf.erb: -------------------------------------------------------------------------------- 1 | # This is a configuration file for Zabbix Java Gateway. 2 | # It is sourced by startup.sh and shutdown.sh scripts. 3 | 4 | ### Option: zabbix.listenIP 5 | # IP address to listen on. 6 | # 7 | LISTEN_IP=<%= @listenip %> 8 | 9 | ### Option: zabbix.listenPort 10 | # Port to listen on. 11 | # 12 | LISTEN_PORT=<%= @listenport %> 13 | 14 | ### Option: zabbix.pidFile 15 | # Name of PID file. 16 | # If omitted, Zabbix Java Gateway is started as a console application. 17 | # 18 | PID_FILE=<%= @real_pidfile %> 19 | 20 | ### Option: zabbix.startPollers 21 | # Number of worker threads to start. 22 | # 23 | START_POLLERS=<%= @startpollers %> 24 | 25 | ### Option: zabbix.timeout 26 | # How long to wait for network operations 27 | # Mandatory: No 28 | # Range: 1-30 29 | # Default: 3 30 | # 31 | TIMEOUT=<%= @timeout %> 32 | -------------------------------------------------------------------------------- /types/databases.pp: -------------------------------------------------------------------------------- 1 | # @summary Type for supported databases by the zabbix module 2 | type Zabbix::Databases = Enum['postgresql', 'mysql', 'sqlite'] 3 | -------------------------------------------------------------------------------- /types/historyics.pp: -------------------------------------------------------------------------------- 1 | # @summary Type for size values in bytes (also allows k/K and m/M as appendix) 2 | type Zabbix::Historyics = Optional[Pattern[/^\d+[k|K|m|M]?$/]] 3 | --------------------------------------------------------------------------------