├── .editorconfig
├── .fixtures.yml
├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
├── labeler.yml
├── release.yml
└── workflows
│ ├── ci.yml
│ ├── labeler.yml
│ ├── prepare_release.yml
│ └── release.yml
├── .gitignore
├── .msync.yml
├── .overcommit.yml
├── .pmtignore
├── .puppet-lint.rc
├── .rubocop.yml
├── .rubocop_todo.yml
├── .sync.yml
├── CHANGELOG.md
├── Gemfile
├── HACKING.md
├── HISTORY.md
├── LICENSE
├── NATIVE_TYPES_AND_PROVIDERS.md
├── README.md
├── REFERENCE.md
├── Rakefile
├── Vagrantfile
├── examples
├── FreeBSD.pp
├── OpenBSD.pp
├── RedHatEnterpriseServer.pp
├── Ubuntu.pp
├── job-configuration
│ ├── build.pp
│ └── templates
│ │ └── build.xml.erb
└── plugin-configuration
│ ├── git.pp
│ └── templates
│ └── git.config.xml.erb
├── files
└── puppet_helper.groovy
├── lib
├── facter
│ └── jenkins.rb
└── puppet
│ ├── jenkins.rb
│ ├── jenkins
│ └── plugins.rb
│ ├── parser
│ └── functions
│ │ ├── jenkins_port.rb
│ │ └── jenkins_prefix.rb
│ ├── provider
│ ├── jenkins_authorization_strategy
│ │ └── cli.rb
│ ├── jenkins_credentials
│ │ └── cli.rb
│ ├── jenkins_job
│ │ └── cli.rb
│ ├── jenkins_num_executors
│ │ └── cli.rb
│ ├── jenkins_security_realm
│ │ └── cli.rb
│ ├── jenkins_slaveagent_port
│ │ └── cli.rb
│ └── jenkins_user
│ │ └── cli.rb
│ ├── type
│ ├── jenkins_authorization_strategy.rb
│ ├── jenkins_credentials.rb
│ ├── jenkins_job.rb
│ ├── jenkins_num_executors.rb
│ ├── jenkins_security_realm.rb
│ ├── jenkins_slaveagent_port.rb
│ └── jenkins_user.rb
│ └── x
│ ├── jenkins.rb
│ └── jenkins
│ ├── config.rb
│ ├── provider.rb
│ ├── provider
│ └── cli.rb
│ ├── type.rb
│ ├── type
│ └── cli.rb
│ └── util.rb
├── manifests
├── augeas.pp
├── cli.pp
├── cli
│ ├── config.pp
│ ├── exec.pp
│ └── reload.pp
├── cli_helper.pp
├── config.pp
├── credentials.pp
├── direct_download.pp
├── firewall.pp
├── init.pp
├── job.pp
├── job
│ ├── absent.pp
│ └── present.pp
├── jobs.pp
├── master.pp
├── package.pp
├── params.pp
├── plugin.pp
├── plugins.pp
├── proxy.pp
├── repo.pp
├── repo
│ ├── debian.pp
│ ├── el.pp
│ └── suse.pp
├── security.pp
├── service.pp
├── slave.pp
├── user.pp
├── user_setup.pp
└── users.pp
├── metadata.json
├── spec
├── acceptance
│ ├── class_spec.rb
│ ├── hieradata
│ │ ├── common.yaml
│ │ └── family
│ │ │ ├── Debian.yaml
│ │ │ └── RedHat.yaml
│ ├── job_spec.rb
│ ├── plugin_spec.rb
│ ├── slave_spec.rb
│ └── xtypes
│ │ ├── jenkins_credentials_spec.rb
│ │ └── jenkins_job_spec.rb
├── classes
│ ├── cli
│ │ └── config_spec.rb
│ ├── jenkins_cli_helper_spec.rb
│ ├── jenkins_cli_spec.rb
│ ├── jenkins_config_spec.rb
│ ├── jenkins_direct_download_spec.rb
│ ├── jenkins_firewall_spec.rb
│ ├── jenkins_jobs_spec.rb
│ ├── jenkins_master_spec.rb
│ ├── jenkins_package_spec.rb
│ ├── jenkins_plugins_spec.rb
│ ├── jenkins_proxy_spec.rb
│ ├── jenkins_repo_debian_spec.rb
│ ├── jenkins_repo_el_spec.rb
│ ├── jenkins_repo_spec.rb
│ ├── jenkins_repo_suse_spec.rb
│ ├── jenkins_security_spec.rb
│ ├── jenkins_slave_spec.rb
│ ├── jenkins_spec.rb
│ ├── jenkins_user_setup_spec.rb
│ └── jenkins_users_spec.rb
├── defines
│ ├── jenkins_augeas_spec.rb
│ ├── jenkins_cli_exec_spec.rb
│ ├── jenkins_credentials_spec.rb
│ ├── jenkins_job_present_spec.rb
│ ├── jenkins_job_spec.rb
│ ├── jenkins_plugin_spec.rb
│ └── jenkins_user_spec.rb
├── fixtures
│ └── testjob.xml
├── functions
│ ├── jenkins_port_spec.rb
│ └── jenkins_prefix_spec.rb
├── setup_acceptance_node.pp
├── spec_helper.rb
├── spec_helper_acceptance.rb
└── unit
│ ├── facter
│ └── plugins_spec.rb
│ ├── jenkins_plugins_spec.rb
│ ├── jenkins_spec.rb
│ └── puppet
│ ├── provider
│ ├── jenkins_authorization_strategy
│ │ └── cli_spec.rb
│ ├── jenkins_credentials
│ │ └── cli_spec.rb
│ ├── jenkins_job
│ │ └── cli_spec.rb
│ ├── jenkins_num_executors
│ │ └── cli_spec.rb
│ ├── jenkins_security_realm
│ │ └── cli_spec.rb
│ ├── jenkins_slaveagent_port
│ │ └── cli_spec.rb
│ └── jenkins_user
│ │ └── cli_spec.rb
│ ├── type
│ ├── jenkins_authorization_strategy_spec.rb
│ ├── jenkins_credentials_spec.rb
│ ├── jenkins_job_spec.rb
│ ├── jenkins_num_executors_spec.rb
│ ├── jenkins_security_realm_spec.rb
│ ├── jenkins_slaveagent_port_spec.rb
│ └── jenkins_user_spec.rb
│ └── x
│ ├── jenkins
│ ├── config_spec.rb
│ ├── provider
│ │ └── cli_spec.rb
│ ├── type
│ │ └── cli_spec.rb
│ └── util_spec.rb
│ ├── spec_jenkins_providers.rb
│ └── spec_jenkins_types.rb
├── templates
├── jenkins-override.epp
├── jenkins-slave-defaults.erb
├── jenkins-slave-run.erb
├── jenkins-slave.service.erb
├── org.jenkins-ci.slave.jnlp.plist.epp
└── proxy.xml.erb
└── types
└── tunnel.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 | apt: "https://github.com/puppetlabs/puppetlabs-apt"
5 | stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib"
6 | java: "https://github.com/puppetlabs/puppetlabs-java"
7 | zypprepo: "https://github.com/voxpupuli/puppet-zypprepo.git"
8 | archive: "https://github.com/voxpupuli/puppet-archive.git"
9 | systemd: "https://github.com/voxpupuli/puppet-systemd"
10 | yumrepo_core: https://github.com/puppetlabs/puppetlabs-yumrepo_core.git
11 | augeas_core: https://github.com/puppetlabs/puppetlabs-augeas_core.git
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
10 |
11 | ## Affected Puppet, Ruby, OS and module versions/distributions
12 |
13 | - Puppet:
14 | - Ruby:
15 | - Distribution:
16 | - Module version:
17 |
18 | ## How to reproduce (e.g Puppet code you use)
19 |
20 | ## What are you seeing
21 |
22 | ## What behaviour did you expect instead
23 |
24 | ## Output log
25 |
26 | ## Any additional information you'd like to impart
27 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
9 | #### Pull Request (PR) description
10 |
13 |
14 | #### This Pull Request (PR) fixes the following issues
15 |
21 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | skip-changelog:
6 | - head-branch: ['^release-*', 'release']
7 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | # https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes
6 |
7 | changelog:
8 | exclude:
9 | labels:
10 | - duplicate
11 | - invalid
12 | - modulesync
13 | - question
14 | - skip-changelog
15 | - wont-fix
16 | - wontfix
17 |
18 | categories:
19 | - title: Breaking Changes 🛠
20 | labels:
21 | - backwards-incompatible
22 |
23 | - title: New Features 🎉
24 | labels:
25 | - enhancement
26 |
27 | - title: Bug Fixes 🐛
28 | labels:
29 | - bug
30 |
31 | - title: Documentation Updates 📚
32 | labels:
33 | - documentation
34 | - docs
35 |
36 | - title: Dependency Updates ⬆️
37 | labels:
38 | - dependencies
39 |
40 | - title: Other Changes
41 | labels:
42 | - "*"
43 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | name: CI
6 |
7 | # yamllint disable-line rule:truthy
8 | on:
9 | pull_request: {}
10 | push:
11 | branches:
12 | - main
13 | - master
14 |
15 | concurrency:
16 | group: ${{ github.ref_name }}
17 | cancel-in-progress: true
18 |
19 | jobs:
20 | puppet:
21 | name: Puppet
22 | uses: voxpupuli/gha-puppet/.github/workflows/beaker.yml@v3
23 |
--------------------------------------------------------------------------------
/.github/workflows/labeler.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | name: "Pull Request Labeler"
6 |
7 | # yamllint disable-line rule:truthy
8 | on:
9 | pull_request_target: {}
10 |
11 | jobs:
12 | labeler:
13 | permissions:
14 | contents: read
15 | pull-requests: write
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/labeler@v5
19 |
--------------------------------------------------------------------------------
/.github/workflows/prepare_release.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | name: 'Prepare Release'
6 |
7 | on:
8 | workflow_dispatch:
9 | inputs:
10 | version:
11 | description: 'Module version to be released. Must be a valid semver string without leading v. (1.2.3)'
12 | required: false
13 |
14 | jobs:
15 | release_prep:
16 | uses: 'voxpupuli/gha-puppet/.github/workflows/prepare_release.yml@v3'
17 | with:
18 | version: ${{ github.event.inputs.version }}
19 | allowed_owner: 'voxpupuli'
20 | secrets:
21 | # Configure secrets here:
22 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets
23 | github_pat: '${{ secrets.PCCI_PAT_RELEASE_PREP }}'
24 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | name: Release
6 |
7 | # yamllint disable-line rule:truthy
8 | on:
9 | push:
10 | tags:
11 | - '*'
12 |
13 | jobs:
14 | release:
15 | name: Release
16 | uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v3
17 | with:
18 | allowed_owner: 'voxpupuli'
19 | secrets:
20 | # Configure secrets here:
21 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets
22 | username: ${{ secrets.PUPPET_FORGE_USERNAME }}
23 | api_key: ${{ secrets.PUPPET_FORGE_API_KEY }}
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Managed by modulesync - DO NOT EDIT
2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
3 |
4 | /pkg/
5 | /Gemfile.lock
6 | /Gemfile.local
7 | /vendor/
8 | /.vendor/
9 | /spec/fixtures/manifests/
10 | /spec/fixtures/modules/
11 | /.vagrant/
12 | /.bundle/
13 | /.ruby-version
14 | /coverage/
15 | /log/
16 | /.idea/
17 | /.dependencies/
18 | /.librarian/
19 | /Puppetfile.lock
20 | *.iml
21 | .*.sw?
22 | /.yardoc/
23 | /Guardfile
24 | bolt-debug.log
25 | .rerun.json
26 |
--------------------------------------------------------------------------------
/.msync.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Managed by modulesync - DO NOT EDIT
3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
4 |
5 | modulesync_config_version: '9.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_documentation-check
6 | --no-parameter_types-check
7 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | ---
2 | inherit_from: .rubocop_todo.yml
3 |
4 | inherit_gem:
5 | voxpupuli-test: rubocop.yml
6 |
7 | Lint/ConstantDefinitionInBlock:
8 | Enabled: false
9 |
10 | RSpec/ExpectInHook:
11 | Enabled: false
12 |
13 | RSpec/LeakyConstantDeclaration:
14 | Enabled: false
15 |
16 | RSpec/MessageSpies:
17 | Enabled: false
18 |
19 | RSpec/MultipleMemoizedHelpers:
20 | Enabled: false
21 |
22 | RSpec/StubbedMock:
23 | Enabled: false
24 |
25 | Style/ClassVars:
26 | Enabled: false
27 |
28 | Style/IfUnlessModifier:
29 | Enabled: false
30 |
--------------------------------------------------------------------------------
/.rubocop_todo.yml:
--------------------------------------------------------------------------------
1 | # This configuration was generated by
2 | # `rubocop --auto-gen-config`
3 | # on 2023-08-17 21:33:46 UTC using RuboCop version 1.50.2.
4 | # The point is for the user to remove these configuration records
5 | # one by one as the offenses are removed from the code base.
6 | # Note that changes in the inspected code, or installation of new
7 | # versions of RuboCop, may require this file to be generated again.
8 |
9 | # Offense count: 9
10 | # This cop supports unsafe autocorrection (--autocorrect-all).
11 | RSpec/BeEq:
12 | Exclude:
13 | - 'spec/unit/puppet/provider/jenkins_job/cli_spec.rb'
14 | - 'spec/unit/puppet/x/jenkins/provider/cli_spec.rb'
15 |
16 | # Offense count: 2
17 | # This cop supports unsafe autocorrection (--autocorrect-all).
18 | # Configuration parameters: .
19 | # SupportedStyles: constant, string
20 | RSpec/VerifiedDoubleReference:
21 | EnforcedStyle: string
22 |
23 | # Offense count: 1
24 | # This cop supports unsafe autocorrection (--autocorrect-all).
25 | Style/SlicingWithRange:
26 | Exclude:
27 | - 'lib/puppet/jenkins/plugins.rb'
28 |
--------------------------------------------------------------------------------
/.sync.yml:
--------------------------------------------------------------------------------
1 | ---
2 | .rubocop.yml:
3 | unmanaged: true
4 |
--------------------------------------------------------------------------------
/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', '~> 9.0', :require => false
8 | gem 'coveralls', :require => false
9 | gem 'simplecov-console', :require => false
10 | gem 'puppet_metadata', '~> 4.0', :require => false
11 | end
12 |
13 | group :development do
14 | gem 'guard-rake', :require => false
15 | gem 'overcommit', '>= 0.39.1', :require => false
16 | end
17 |
18 | group :system_tests do
19 | gem 'voxpupuli-acceptance', '~> 3.0', :require => false
20 | end
21 |
22 | group :release do
23 | gem 'voxpupuli-release', '~> 3.0', :require => false
24 | end
25 |
26 | gem 'rake', :require => false
27 | gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test]
28 |
29 | puppetversion = ENV['PUPPET_GEM_VERSION'] || [">= 7.24", "< 9"]
30 | gem 'puppet', puppetversion, :require => false, :groups => [:test]
31 |
32 | # vim: syntax=ruby
33 |
--------------------------------------------------------------------------------
/HACKING.md:
--------------------------------------------------------------------------------
1 | # Developing/Contributing
2 |
3 | ## Testing
4 |
5 | This module has behavior tests written using [RSpec 2](https://www.relishapp.com/rspec),
6 | is syntax checked with [puppet-syntax](https://github.com/gds-operations/puppet-syntax), and style checked with [puppet-lint](http://puppet-lint.com/).
7 | The goal of these tests are to validate the expected behavior of the module.
8 | As more features and platform support are added to this module the tests
9 | provide an automated way to validate the expectations previous contributors
10 | have specified.
11 |
12 | In order to validate behavior setup fixtures with `rake spec_prep` and then
13 | execute code with `rake spec_standalone`.
14 |
15 | % rake spec_standalone
16 | (in /Users/jeff/vms/puppet/modules/jenkins)
17 | .
18 | Finished in 0.31279 seconds
19 | 1 example, 0 failures
20 |
21 | Lint, spec, and syntax checks can be run by using the default rake task by
22 | simply running 'rake'.
23 |
24 | ### Lint checking
25 |
26 | The lint checks require the `puppet-lint` gem to be installed. Running
27 | 'rake lint' will lint check all of the *.pp files to ensure they conform to the
28 | puppet style guide.
29 |
30 | ### RSpec Testing Requirements
31 |
32 | The spec tests require the `rspec-puppet` gem to be installed. Running 'rake spec'
33 | will automatically check out all of the modules in the .fixtures.yml needed to run
34 | the tests.
35 |
36 | ### Syntax checking
37 |
38 | The syntax checks require the `puppet-syntax` gem to be installed. Running
39 | 'rake syntax' will sytanx check the manifests and templates.
40 |
41 | ### Installing Testing Requirements
42 |
43 | To install the testing requirements:
44 |
45 | % gem install rspec-puppet puppet-lint puppet-syntax --no-ri --no-rdoc
46 | Successfully installed rspec-core-2.14.5
47 | Successfully installed diff-lcs-1.2.4
48 | Successfully installed rspec-expectations-2.14.3
49 | Successfully installed rspec-mocks-2.14.3
50 | Successfully installed rspec-2.14.1
51 | Successfully installed rspec-puppet-0.1.6
52 | Successfully installed puppet-lint-0.3.2
53 | Successfully installed rake-10.1.0
54 | Successfully installed puppet-syntax-1.1.0
55 | 10 gems installed
56 |
57 | ### Adding Tests
58 |
59 | Please see the [rspec-puppet](https://github.com/rodjek/rspec-puppet) project
60 | for information on writing tests. A basic test that validates the class is
61 | declared in the catalog is provided in the file
62 | `spec/classes/jenkins_spec.rb`. `rspec-puppet` automatically uses the top
63 | level description as the name of a module to include in the catalog.
64 | Resources may be validated in the catalog using:
65 |
66 | * `contain_class('myclass')`
67 | * `contain_service('sshd')`
68 | * `contain_file('/etc/puppet')`
69 | * `contain_package('puppet')`
70 | * And so forth for other Puppet resources.
71 |
72 | ## Acceptance testings
73 |
74 | Acceptance tests are setup using [Beaker](https://github.com/puppetlabs/beaker), which will spin up an instance (by default [Vagrant](https://www.vagrantup.com/), but also supports various VPC's), apply the puppet code against this spun up node and then uses [Serverspec](http://serverspec.org/) tests to validate behaviour.
75 |
76 | To run the tests:
77 |
78 | * `bundle exec rspec spec/acceptance/`
79 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Managed by modulesync - DO NOT EDIT
2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/
3 |
4 | # Attempt to load voxpupuli-test (which pulls in puppetlabs_spec_helper),
5 | # otherwise attempt to load it directly.
6 | begin
7 | require 'voxpupuli/test/rake'
8 | rescue LoadError
9 | begin
10 | require 'puppetlabs_spec_helper/rake_tasks'
11 | rescue LoadError
12 | end
13 | end
14 |
15 | # load optional tasks for acceptance
16 | # only available if gem group releases is installed
17 | begin
18 | require 'voxpupuli/acceptance/rake'
19 | rescue LoadError
20 | end
21 |
22 | # load optional tasks for releases
23 | # only available if gem group releases is installed
24 | begin
25 | require 'voxpupuli/release/rake_tasks'
26 | rescue LoadError
27 | # voxpupuli-release not present
28 | else
29 | GCGConfig.user = 'voxpupuli'
30 | GCGConfig.project = 'puppet-jenkins'
31 | end
32 |
33 | desc "Run main 'test' task and report merged results to coveralls"
34 | task test_with_coveralls: [:test] do
35 | if Dir.exist?(File.expand_path('../lib', __FILE__))
36 | require 'coveralls/rake/task'
37 | Coveralls::RakeTask.new
38 | Rake::Task['coveralls:push'].invoke
39 | else
40 | puts 'Skipping reporting to coveralls. Module has no lib dir'
41 | end
42 | end
43 |
44 | # vim: syntax=ruby
45 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | require 'yaml'
2 | ENV['VAGRANT_DEFAULT_PROVIDER'] = 'aws'
3 |
4 | Vagrant.configure('2') do |config|
5 | access_key_id = File.read('.vagrant_key_id').chomp
6 | secret_access_key = File.read('.vagrant_secret_access_key').chomp
7 | keypair = File.read('.vagrant_keypair_name').chomp
8 |
9 | config.vm.box = 'dummy'
10 |
11 | Dir['spec/serverspec/*'].each do |dname|
12 | next unless File.directory?(dname)
13 | # Convert spec/serverspec/ubuntu-precise into 'ubuntu-precise'
14 | name = File.basename(dname)
15 | spec_config = YAML.load_file(File.join(dname + '/config.yml'))
16 |
17 | config.vm.synced_folder '.', '/vagrant/jenkins', type: 'rsync'
18 |
19 | config.vm.define(name) do |node|
20 | # This is a Vagrant-local hack to make sure we have properly udpated apt
21 | # caches since AWS machines are definitely going to have stale ones
22 | node.vm.provision 'shell',
23 | :inline => 'if [ ! -f "/apt-cached" ]; then apt-get update && touch /apt-cached; fi'
24 | node.vm.provision 'shell',
25 | :inline => 'ln -sf /tmp/vagrant-puppet-2/modules-0 /tmp/vagrant-puppet-2/modules-0/jenkins'
26 |
27 | node.vm.provision 'puppet' do |pp|
28 | pp.module_path = [
29 | '.',
30 | 'spec/fixtures/modules',
31 | ]
32 | pp.manifests_path = "spec/serverspec/#{name}/manifests"
33 | end
34 |
35 |
36 | node.vm.provision :serverspec do |spec|
37 | spec.pattern = "spec/serverspec/#{name}/*_spec.rb"
38 | end
39 |
40 | node.vm.provider :aws do |aws, override|
41 | aws.access_key_id = access_key_id
42 | aws.secret_access_key = secret_access_key
43 | aws.keypair_name = keypair
44 |
45 | hostname = "vagrant-jenkins-#{name}"
46 | # Ensuring that our machines hostname is "correct" so Puppet will apply
47 | # the right resources to it
48 | aws.user_data = "#!/bin/sh
49 | echo '#{hostname}' > /etc/hostname;
50 | hostname '#{hostname}';"
51 |
52 | aws.tags = {:Name => hostname}
53 |
54 | # Ubuntu LTS 12.04 in us-west-2 with Puppet installed from the Puppet
55 | # Labs apt repository
56 | aws.ami = spec_config['ami']
57 | aws.region = spec_config['region']
58 | override.ssh.username = spec_config['username']
59 | override.ssh.private_key_path = File.expand_path('~/.ssh/id_rsa')
60 | end
61 | end
62 | end
63 | end
64 |
65 | # vim: ft=ruby
66 |
--------------------------------------------------------------------------------
/examples/FreeBSD.pp:
--------------------------------------------------------------------------------
1 | node default {
2 | # Requires Module zleslie-pkgng
3 |
4 | Package {
5 | provider => 'pkgng',
6 | }
7 |
8 | package { 'openjdk':
9 | ensure => installed,
10 | }
11 | -> class { 'jenkins':
12 | install_java => false,
13 | repo => false,
14 | }
15 | # Runs on Port 8180
16 | }
17 |
--------------------------------------------------------------------------------
/examples/OpenBSD.pp:
--------------------------------------------------------------------------------
1 | node default {
2 | package { 'jre':
3 | ensure => installed,
4 | }
5 | -> class { 'jenkins':
6 | install_java => false,
7 | repo => false,
8 | }
9 | # Runs on Port 8000
10 | }
11 |
--------------------------------------------------------------------------------
/examples/RedHatEnterpriseServer.pp:
--------------------------------------------------------------------------------
1 | node default {
2 | include jenkins
3 |
4 | jenkins::plugin {
5 | 'ansicolor' :
6 | version => '0.3.1';
7 | }
8 |
9 | jenkins::job {
10 | 'build' :
11 | config => '
12 |
13 |
14 |
15 | false
16 |
17 |
18 | true
19 | false
20 | false
21 | false
22 |
23 | false
24 |
25 |
26 |
27 | ';
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/Ubuntu.pp:
--------------------------------------------------------------------------------
1 | node default {
2 | include jenkins
3 |
4 | jenkins::plugin {
5 | 'ansicolor' :
6 | version => '0.3.1';
7 | }
8 |
9 | jenkins::job {
10 | 'build' :
11 | config => '
12 |
13 |
14 |
15 | false
16 |
17 |
18 | true
19 | false
20 | false
21 | false
22 |
23 | false
24 |
25 |
26 |
27 | ';
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/job-configuration/build.pp:
--------------------------------------------------------------------------------
1 | # lint:ignore:autoloader_layout
2 | class jenkins::job::build (
3 | # lint:endignore
4 | $config = undef,
5 | $jobname = $title,
6 | $ensure = 'present',
7 | ) {
8 | if $config == undef {
9 | $real_content = template('jenkins/job/build.xml.erb')
10 | } else {
11 | $real_content = $config
12 | }
13 |
14 | jenkins::job { 'build':
15 | ensure => $ensure,
16 | jobname => $jobname,
17 | config => $real_content,
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/job-configuration/templates/build.xml.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 |
7 |
8 | true
9 | false
10 | false
11 | false
12 |
13 | false
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/examples/plugin-configuration/git.pp:
--------------------------------------------------------------------------------
1 | # lint:ignore:autoloader_layout
2 | class jenkins::plugin::git (
3 | # lint:endignore
4 | $version = 0,
5 | $config_filename = 'hudson.plugins.git.GitSCM.xml',
6 | $config_content = undef,
7 | $git_name = 'Jenkins',
8 | $git_email = 'jenkins@example.net',
9 | Boolean $git_create_account = false,
10 | ) {
11 | if $config_content == undef {
12 | $real_content = template('jenkins/plugin/git.config.xml.erb')
13 | } else {
14 | $real_content = $config_content
15 | }
16 |
17 | jenkins::plugin { 'git':
18 | version => $version,
19 | config_filename => $config_filename,
20 | config_content => $real_content,
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/examples/plugin-configuration/templates/git.config.xml.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1
4 | <%= @git_name %>
5 | <%= @git_email %>
6 | <%= @git_create_account %>
7 |
8 |
--------------------------------------------------------------------------------
/lib/facter/jenkins.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # jenkins.rb
4 | #
5 | # Creates a fact 'jenkins_plugins' containing a comma-delimited string of all
6 | # jenkins plugins + versions.
7 | require 'facter'
8 | require_relative '../puppet/jenkins/plugins'
9 |
10 | Facter.add(:jenkins_plugins) do
11 | confine kernel: 'Linux'
12 | setcode do
13 | plugins = Puppet::Jenkins::Plugins.available
14 | plugins.keys.sort.map { |plugin| "#{plugin} #{plugins[plugin][:plugin_version]}" }.join(', ')
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/puppet/jenkins.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Puppet
4 | module Jenkins
5 | # @return [String] Full path to the Jenkins user's home directory
6 | def self.home_dir
7 | File.expand_path('~jenkins')
8 | rescue ArgumentError
9 | # The Jenkins user doesn't exist!
10 | nil
11 | end
12 |
13 | # @return [String] Full path to the Jenkins user's plugin directory
14 | def self.plugins_dir
15 | File.join(home_dir, 'plugins')
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/lib/puppet/jenkins/plugins.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../jenkins'
4 |
5 | module Puppet
6 | module Jenkins
7 | module Plugins
8 | # Return structured data for the given plugin manifest string
9 | #
10 | # @return [Hash] A hash containing symbolized manifest keys and their
11 | # string values
12 | # @return [NilClass] A nil if +manifest_str+ nil or an empty string
13 | def self.manifest_data(manifest_str)
14 | return {} if manifest_str.nil? || manifest_str.empty?
15 |
16 | data = {}
17 | manifest_str.split("\n").each do |line|
18 | next if line.empty?
19 |
20 | # Parse out "Plugin-Version: 1.2" for example
21 | parts = line.split(': ')
22 |
23 | # If the line starts with a space or we can't get at least two parts
24 | # (key and value), that means it's really just a word-wrap from the
25 | # previous line, and not a key, skip!
26 | next if parts.size < 2
27 | next if parts.first[0] == ' '
28 |
29 | key = parts.first.downcase.tr('-', '_').chomp
30 | # Skip garbage keys
31 | next if key.nil? || key.empty?
32 |
33 | # Re-join any colon delimited strings in the value back together,
34 | # e.g.: "http://wiki.jenkins-ci.org/display/JENKINS/Ant+Plugin"
35 | value = parts[1..-1].join(':').chomp
36 |
37 | data[key.to_sym] = value
38 | end
39 |
40 | data
41 | end
42 |
43 | # @return [Hash] a +Hash+ containing a mapping of a plugin name to its
44 | # manifest data
45 | def self.available
46 | return {} unless exists?
47 |
48 | plugins = {}
49 | Dir.entries(Puppet::Jenkins.plugins_dir).each do |plugin|
50 | # Skip useless directories
51 | next if plugin == '..'
52 | next if plugin == '.'
53 |
54 | plugin_dir = File.join(Puppet::Jenkins.plugins_dir, plugin)
55 | # Without an unpacked plugin directory, we can't find a version
56 | next unless File.directory?(plugin_dir)
57 |
58 | manifest = File.join(plugin_dir, 'META-INF', 'MANIFEST.MF')
59 | begin
60 | manifest = manifest_data(File.read(manifest))
61 | plugins[plugin] = manifest if manifest
62 | rescue StandardError
63 | # Nothing really to do about it, failing means no version which will
64 | # result in a new plugin if needed
65 | nil
66 | end
67 | end
68 | plugins
69 | end
70 |
71 | # Determine whether or not the jenkins plugin directory exists
72 | #
73 | # @return [Boolean] T
74 | def self.exists?
75 | home = Puppet::Jenkins.home_dir
76 | return false if home.nil?
77 | return false unless File.directory? Puppet::Jenkins.plugins_dir
78 |
79 | true
80 | end
81 | end
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/lib/puppet/parser/functions/jenkins_port.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Puppet::Parser::Functions
4 | newfunction(:jenkins_port, type: :rvalue, doc: <<-ENDHEREDOC) do |_args|
5 | Return the configurad Jenkins port value
6 | (corresponds to /etc/defaults/jenkins -> JENKINS_PORT
7 |
8 | Example:
9 |
10 | $port = jenkins_port()
11 | ENDHEREDOC
12 |
13 | config_hash = lookupvar('jenkins::config_hash')
14 | config_hash&.dig('JENKINS_PORT', 'value') || 8080
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/puppet/parser/functions/jenkins_prefix.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Puppet::Parser::Functions
4 | newfunction(:jenkins_prefix, type: :rvalue, doc: <<-ENDHEREDOC) do |_args|
5 | Return the configured Jenkins prefix value
6 | (corresponds to /etc/defaults/jenkins -> PREFIX)
7 |
8 | Example:
9 |
10 | $prefix = jenkins_prefix()
11 | ENDHEREDOC
12 |
13 | config_hash = lookupvar('jenkins::config_hash')
14 | config_hash&.dig('PREFIX', 'value') || ''
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_authorization_strategy/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/util')
4 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
5 |
6 | require 'json'
7 |
8 | Puppet::Type.type(:jenkins_authorization_strategy).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
9 | mk_resource_methods
10 |
11 | def self.instances(catalog = nil)
12 | all = get_authorization_strategy(catalog)
13 |
14 | # we are assuming there is only one key hash
15 | Puppet.debug("#{sname} instances: #{all.keys}")
16 |
17 | [from_hash(all)]
18 | end
19 |
20 | def flush
21 | @property_hash = resource.to_hash unless resource.nil?
22 |
23 | case self.ensure
24 | when :present
25 | set_jenkins_instance
26 | when :absent
27 | set_strategy_unsecured
28 | else
29 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
30 | end
31 | end
32 |
33 | private
34 |
35 | def self.from_hash(info)
36 | method_name = 'setAuthorizationStrategy'
37 | class_name = info[method_name].keys.first
38 | ctor_args = info[method_name][class_name]
39 |
40 | args = {
41 | name: class_name,
42 | ensure: :present,
43 | arguments: ctor_args
44 | }
45 |
46 | # map nil -> :undef
47 | args = Puppet::X::Jenkins::Util.undefize(args)
48 | new(args)
49 | end
50 | private_class_method :from_hash
51 |
52 | def to_hash
53 | ctor = {}
54 |
55 | ctor[name] = if arguments == :absent
56 | []
57 | else
58 | arguments
59 | end
60 | Puppet.debug("to_hash arguments #{arguments}")
61 |
62 | info = { 'setAuthorizationStrategy' => ctor }
63 | # map :undef -> nil
64 | Puppet::X::Jenkins::Util.unundef(info)
65 | end
66 |
67 | # jenkins only supports a single configured security realm at a time
68 | def self.get_authorization_strategy(catalog = nil)
69 | raw = clihelper(['get_authorization_strategy'], catalog: catalog)
70 |
71 | begin
72 | JSON.parse(raw)
73 | rescue JSON::ParserError
74 | raise Puppet::Error, "unable to parse as JSON: #{raw}"
75 | end
76 | end
77 | private_class_method :get_authorization_strategy
78 |
79 | def set_jenkins_instance(input = nil)
80 | input ||= to_hash
81 |
82 | clihelper(['set_jenkins_instance'], stdinjson: input)
83 | end
84 |
85 | def set_strategy_unsecured
86 | input = {
87 | 'setAuthorizationStrategy' => {
88 | 'hudson.security.AuthorizationStrategy$Unsecured' => []
89 | }
90 | }
91 | set_jenkins_instance(input)
92 | end
93 | end
94 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_credentials/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'puppet/util/warnings'
4 |
5 | require 'json'
6 |
7 | require_relative '../../../puppet/x/jenkins/util'
8 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
9 |
10 | Puppet::Type.type(:jenkins_credentials).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
11 | mk_resource_methods
12 |
13 | def self.instances(catalog = nil)
14 | all = credentials_list_json(catalog)
15 |
16 | Puppet.debug("#{sname} instances: #{all.map { |i| i['id'] }}")
17 |
18 | all.map { |info| from_hash(info) }
19 | end
20 |
21 | def flush
22 | @property_hash = resource.to_hash unless resource.nil?
23 |
24 | case self.ensure
25 | when :present
26 | credentials_update_json
27 | when :absent
28 | credentials_delete_id
29 | else
30 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
31 | end
32 | end
33 |
34 | private
35 |
36 | def self.copy_key(dst, src, key)
37 | dst[key.to_sym] = src[key.to_s]
38 | end
39 | private_class_method :copy_key
40 |
41 | def self.from_hash(info)
42 | # map nil -> :undef
43 | info = Puppet::X::Jenkins::Util.undefize(info)
44 |
45 | params = {
46 | name: info['id'],
47 | ensure: :present
48 | }
49 |
50 | %i[impl domain scope].each { |k| copy_key(params, info, k) }
51 |
52 | case info['impl']
53 | when 'UsernamePasswordCredentialsImpl'
54 | %i[description username password].each { |k| copy_key(params, info, k) }
55 | when 'BasicSSHUserPrivateKey'
56 | %i[description username private_key passphrase].each { |k| copy_key(params, info, k) }
57 | when 'StringCredentialsImpl'
58 | %i[description secret].each { |k| copy_key(params, info, k) }
59 | when 'FileCredentialsImpl'
60 | %i[description file_name content].each { |k| copy_key(params, info, k) }
61 | when 'CertificateCredentialsImpl'
62 | %i[description password key_store_implementation].each { |k| copy_key(params, info, k) }
63 | when 'AWSCredentialsImpl'
64 | %i[description secret_key access_key].each { |k| copy_key(params, info, k) }
65 | when 'BrowserStackCredentials'
66 | %i[description username access_key].each { |k| copy_key(params, info, k) }
67 | when 'GitLabApiTokenImpl'
68 | %i[description api_token].each { |k| copy_key(params, info, k) }
69 | when 'ConduitCredentialsImpl'
70 | %i[description token url].each { |k| copy_key(params, info, k) }
71 |
72 | ksi = info['key_store_impl']
73 | params['key_store_impl'] = ksi
74 |
75 | case ksi
76 | when 'UploadedKeyStoreSource'
77 | params[:content] = info['content']
78 | when 'FileOnMasterKeyStoreSource'
79 | params[:source] = info['source']
80 | else
81 | Puppet::Util::Warnings.debug_once "#{sname}: unsupported key_store_implementation class #{ksi}"
82 | end
83 | else
84 | Puppet::Util::Warnings.debug_once "#{sname}: unsupported implementation class #{info['impl']}"
85 | end
86 |
87 | new(params)
88 | end
89 | private_class_method :from_hash
90 |
91 | def to_hash
92 | info = { 'id' => name }
93 |
94 | properties = self.class.resource_type.validproperties
95 | properties.reject! { |x| x == :ensure }
96 |
97 | properties.each do |prop|
98 | value = @property_hash[prop]
99 | info[prop.to_s] = value unless value.nil?
100 | end
101 |
102 | # map :undef -> nil
103 | Puppet::X::Jenkins::Util.unundef(info)
104 | end
105 |
106 | # array of hashes for multiple "credentials" entries
107 | def self.credentials_list_json(catalog = nil)
108 | raw = clihelper(['credentials_list_json'], catalog: catalog)
109 |
110 | begin
111 | JSON.parse(raw)
112 | rescue JSON::ParserError
113 | raise Puppet::Error, 'Unable to parse Jenkins credentials list as JSON'
114 | end
115 | end
116 | private_class_method :credentials_list_json
117 |
118 | def credentials_update_json
119 | clihelper(['credentials_update_json'], stdinjson: to_hash)
120 | end
121 |
122 | def credentials_delete_id
123 | # name == "id"
124 | clihelper(['credentials_delete_id', name])
125 | end
126 | end
127 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_job/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'puppet/util/warnings'
4 |
5 | require 'json'
6 |
7 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/util')
8 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
9 |
10 | Puppet::Type.type(:jenkins_job).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
11 | mk_resource_methods
12 |
13 | def self.instances(catalog = nil)
14 | jobs = job_list_json(catalog)
15 |
16 | Puppet.debug("#{sname} instances: #{jobs.map { |i| i['name'] }}")
17 |
18 | jobs.map do |job|
19 | new(
20 | name: job['name'],
21 | ensure: :present,
22 | config: job['config'],
23 | enable: job['enabled']
24 | )
25 | end
26 | end
27 |
28 | # ignore #create so we can differentiate in #flush between an update to an
29 | # existing job and creating a new one
30 | def create; end
31 |
32 | def flush
33 | update = false
34 | update = true if exists?
35 |
36 | @property_hash = resource.to_hash unless resource.nil?
37 |
38 | # XXX the enable property is being ignored on flush because this modifies
39 | # the configuration string and breaks idempotent. Should the property be
40 | # removed?
41 | case self.ensure
42 | when :present
43 | if update
44 | update_job if replace
45 | else
46 | create_job
47 | end
48 | when :absent
49 | delete_job
50 | else
51 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
52 | end
53 | end
54 |
55 | private
56 |
57 | # currently unused
58 | def self.list_jobs(catalog = nil)
59 | cli(['list-jobs'], catalog: catalog).split
60 | end
61 | private_class_method :list_jobs
62 |
63 | def self.job_list_json(catalog = nil)
64 | raw = clihelper(['job_list_json'], catalog: catalog)
65 |
66 | begin
67 | JSON.parse(raw)
68 | rescue JSON::ParserError
69 | raise Puppet::Error, "unable to parse as JSON: #{raw}"
70 | end
71 | end
72 | private_class_method :job_list_json
73 |
74 | # currently unused
75 | def self.get_job(job, catalog = nil)
76 | cli(['get-job', job], catalog: catalog)
77 | end
78 | private_class_method :get_job
79 |
80 | # currently unused
81 | def self.job_enabled(job, catalog = nil)
82 | raw = clihelper(['job_enabled', job], catalog: catalog)
83 | raw =~ %r{true} ? true : false
84 | end
85 | private_class_method :job_enabled
86 |
87 | def create_job
88 | cli(['create-job', name], stdin: config)
89 | end
90 |
91 | def update_job
92 | cli(['update-job', name], stdin: config)
93 | end
94 |
95 | def delete_job
96 | cli(['delete-job', name])
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_num_executors/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/util')
4 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
5 |
6 | Puppet::Type.type(:jenkins_num_executors).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
7 | mk_resource_methods
8 |
9 | def self.instances(catalog = nil)
10 | n = get_num_executors(catalog)
11 |
12 | # there can be only one value
13 | Puppet.debug("#{sname} instances: #{n}")
14 |
15 | [new(name: n, ensure: :prsent)]
16 | end
17 |
18 | def flush
19 | case self.ensure
20 | when :present
21 | set_num_executors
22 | else
23 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
24 | end
25 | end
26 |
27 | private
28 |
29 | def self.get_num_executors(catalog = nil)
30 | clihelper(['get_num_executors'], catalog: catalog).to_i
31 | end
32 | private_class_method :get_num_executors
33 |
34 | def set_num_executors
35 | clihelper(['set_num_executors', name])
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_security_realm/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/util')
4 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
5 |
6 | require 'json'
7 |
8 | Puppet::Type.type(:jenkins_security_realm).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
9 | mk_resource_methods
10 |
11 | def self.instances(catalog = nil)
12 | all = get_security_realm(catalog)
13 |
14 | # we are assuming there is only one key hash
15 | Puppet.debug("#{sname} instances: #{all.keys}")
16 |
17 | [from_hash(all)]
18 | end
19 |
20 | def flush
21 | @property_hash = resource.to_hash unless resource.nil?
22 |
23 | case self.ensure
24 | when :present
25 | set_jenkins_instance
26 | when :absent
27 | set_security_none
28 | else
29 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
30 | end
31 | end
32 |
33 | private
34 |
35 | def self.from_hash(info)
36 | method_name = 'setSecurityRealm'
37 | class_name = info[method_name].keys.first
38 | ctor_args = info[method_name][class_name]
39 |
40 | args = {
41 | name: class_name,
42 | ensure: :present,
43 | arguments: ctor_args
44 | }
45 |
46 | # map nil -> :undef
47 | args = Puppet::X::Jenkins::Util.undefize(args)
48 | new(args)
49 | end
50 | private_class_method :from_hash
51 |
52 | def to_hash
53 | ctor = {}
54 |
55 | ctor[name] = if arguments == :absent
56 | []
57 | else
58 | arguments
59 | end
60 |
61 | Puppet.debug("to_hash arguments #{arguments}")
62 |
63 | info = { 'setSecurityRealm' => ctor }
64 | # map :undef -> nil
65 | Puppet::X::Jenkins::Util.unundef(info)
66 | end
67 |
68 | # jenkins only supports a single configured security realm at a time
69 | def self.get_security_realm(catalog = nil)
70 | raw = clihelper(['get_security_realm'], catalog: catalog)
71 |
72 | begin
73 | JSON.parse(raw)
74 | rescue JSON::ParserError
75 | raise Puppet::Error, "unable to parse as JSON: #{raw}"
76 | end
77 | end
78 | private_class_method :get_security_realm
79 |
80 | def set_jenkins_instance(input = nil)
81 | input ||= to_hash
82 |
83 | clihelper(['set_jenkins_instance'], stdinjson: input)
84 | end
85 |
86 | def set_security_none
87 | input = {
88 | 'setSecurityRealm' => {
89 | 'hudson.security.SecurityRealm$None' => []
90 | }
91 | }
92 | set_jenkins_instance(input)
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_slaveagent_port/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/util')
4 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
5 |
6 | Puppet::Type.type(:jenkins_slaveagent_port).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
7 | mk_resource_methods
8 |
9 | def self.instances(catalog = nil)
10 | n = get_slaveagent_port(catalog)
11 |
12 | # there can be only one value
13 | Puppet.debug("#{sname} instances: #{n}")
14 |
15 | [new(name: n, ensure: :present)]
16 | end
17 |
18 | def flush
19 | case self.ensure
20 | when :present
21 | set_slaveagent_port
22 | else
23 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
24 | end
25 | end
26 |
27 | private
28 |
29 | def self.get_slaveagent_port(catalog = nil)
30 | clihelper(['get_slaveagent_port'], catalog: catalog).to_i
31 | end
32 | private_class_method :get_slaveagent_port
33 |
34 | def set_slaveagent_port
35 | clihelper(['set_slaveagent_port', name])
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/puppet/provider/jenkins_user/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/util')
4 | require File.join(File.dirname(__FILE__), '../../..', 'puppet/x/jenkins/provider/cli')
5 |
6 | require 'json'
7 |
8 | Puppet::Type.type(:jenkins_user).provide(:cli, parent: Puppet::X::Jenkins::Provider::Cli) do
9 | mk_resource_methods
10 |
11 | def self.instances(catalog = nil)
12 | all = user_info_all(catalog)
13 |
14 | Puppet.debug("#{sname} instances: #{all.map { |i| i['id'] }}")
15 |
16 | all.map { |info| from_hash(info) }
17 | end
18 |
19 | def api_token_public=(_value)
20 | raise Puppet::Error, 'api_token_public is read-only'
21 | end
22 |
23 | def flush
24 | @property_hash = resource.to_hash unless resource.nil?
25 |
26 | case self.ensure
27 | when :present
28 | user_update
29 | when :absent
30 | delete_user
31 | else
32 | raise Puppet::Error, "invalid :ensure value: #{self.ensure}"
33 | end
34 | end
35 |
36 | private
37 |
38 | def self.from_hash(info)
39 | # map nil -> :undef
40 | info = Puppet::X::Jenkins::Util.undefize(info)
41 |
42 | new(name: info['id'],
43 | ensure: :present,
44 | full_name: info['full_name'],
45 | email_address: info['email_address'],
46 | api_token_plain: info['api_token_plain'],
47 | api_token_public: info['api_token_public'],
48 | public_keys: info['public_keys'],
49 | password: info['password'])
50 | end
51 | private_class_method :from_hash
52 |
53 | def to_hash
54 | info = { 'id' => name }
55 |
56 | properties = self.class.resource_type.validproperties
57 | properties.reject! { |x| x == :ensure }
58 | properties.reject! { |x| x == :api_token_public }
59 |
60 | properties.each do |prop|
61 | value = @property_hash[prop]
62 | info[prop.to_s] = value unless value.nil?
63 | end
64 |
65 | # map :undef -> nil
66 | Puppet::X::Jenkins::Util.unundef(info)
67 | end
68 |
69 | # array of hashes for multiple users
70 | def self.user_info_all(catalog = nil)
71 | raw = if catalog.nil?
72 | clihelper(['user_info_all'])
73 | else
74 | clihelper(['user_info_all'], catalog: catalog)
75 | end
76 |
77 | begin
78 | JSON.parse(raw)
79 | rescue JSON::ParserError
80 | raise Puppet::Error, "unable to parse as JSON: #{raw}"
81 | end
82 | end
83 | private_class_method :user_info_all
84 |
85 | def user_update
86 | input ||= to_hash
87 |
88 | clihelper(['user_update'], stdinjson: input)
89 | end
90 |
91 | def delete_user
92 | clihelper(['delete_user', name])
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_authorization_strategy.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../puppet/x/jenkins/type/cli'
4 |
5 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_authorization_strategy) do
6 | @doc = "Manage Jenkins' authorization strategy"
7 |
8 | ensurable
9 |
10 | newparam(:name) do
11 | desc 'Name of the security realm class'
12 | isnamevar
13 | end
14 |
15 | newproperty(:arguments, array_matching: :all) do
16 | desc 'List of arguments to security realm class constructor'
17 | end
18 |
19 | # require all instances of jenkins_user as the authorization strategy being
20 | # converged might require one of those accounts for administrative control
21 | autorequire(:jenkins_user) do
22 | catalog.resources.select do |r|
23 | r.is_a?(Puppet::Type.type(:jenkins_user))
24 | end
25 | end
26 |
27 | # the authorization strategy can potentially lockout all access if it is
28 | # configured but the security realm is none
29 | autorequire(:jenkins_security_realm) do
30 | if self[:ensure] == :present
31 | catalog.resources.select do |r|
32 | r.is_a?(Puppet::Type.type(:jenkins_security_realm))
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_credentials.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../puppet/x/jenkins/type/cli'
4 |
5 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_credentials) do
6 | @doc = <<-EOS
7 | Manage Jenkins' credentials
8 |
9 | XXX The properties specified are not validated against the specified
10 | jenkins class (`impl`)
11 | EOS
12 |
13 | ensurable
14 |
15 | newparam(:name) do
16 | desc 'Id for credentials entry'
17 | isnamevar
18 | end
19 |
20 | newproperty(:domain) do
21 | desc 'credentials domain within jenkins - :undef indicates the "global" domain'
22 | defaultto :undef
23 | newvalues(:undef)
24 | end
25 |
26 | newproperty(:scope) do
27 | desc 'credentials scope within jenkins'
28 | defaultto :GLOBAL
29 | newvalues(:GLOBAL, :SYSTEM)
30 | end
31 |
32 | newproperty(:impl) do
33 | desc 'name of the java class implimenting the credential'
34 | defaultto :UsernamePasswordCredentialsImpl
35 | newvalues(:UsernamePasswordCredentialsImpl,
36 | :BasicSSHUserPrivateKey,
37 | :ConduitCredentialsImpl,
38 | :StringCredentialsImpl,
39 | :FileCredentialsImpl,
40 | :AWSCredentialsImpl,
41 | :GitLabApiTokenImpl,
42 | :BrowserStackCredentials)
43 | end
44 |
45 | newproperty(:description) do
46 | desc 'description of credentials'
47 | defaultto 'Managed by Puppet'
48 | end
49 |
50 | newproperty(:username) do
51 | desc 'username for credentials - UsernamePasswordCredentialsImpl, CertificateCredentialsImpl, BrowserStackCredentials'
52 | end
53 |
54 | newproperty(:password) do
55 | desc 'password - UsernamePasswordCredentialsImpl, CertificateCredentialsImpl'
56 | end
57 |
58 | newproperty(:private_key) do
59 | desc 'ssh private key string - BasicSSHUserPrivateKey'
60 | end
61 |
62 | newproperty(:access_key) do
63 | desc 'AWS access key - AWSCredentialsImpl, BrowserStackCredentials'
64 | end
65 |
66 | newproperty(:secret_key) do
67 | desc 'AWS secret key - AWSCredentialsImpl'
68 | end
69 |
70 | newproperty(:passphrase) do
71 | desc 'passphrase to unlock ssh private key - BasicSSHUserPrivateKey'
72 | end
73 |
74 | newproperty(:secret) do
75 | desc 'secret string - StringCredentialsImpl'
76 | end
77 |
78 | newproperty(:file_name) do
79 | desc 'name of file - FileCredentialsImpl'
80 | end
81 |
82 | newproperty(:content) do
83 | desc 'content of file - FileCredentialsImpl, CertificateCredentialsImpl'
84 | end
85 |
86 | newproperty(:source) do
87 | desc 'content of file - CertificateCredentialsImpl'
88 | end
89 |
90 | newproperty(:key_store_impl) do
91 | desc 'name of the java class implimenting the key store - CertificateCredentialsImpl'
92 | end
93 |
94 | newproperty(:token) do
95 | desc 'conduit token - ConduitCredentialsImpl'
96 | end
97 |
98 | newproperty(:api_token) do
99 | desc 'API token - GitLabApiTokenImpl'
100 | end
101 |
102 | newproperty(:url) do
103 | desc 'URL of phabriactor installation - ConduitCredentialsImpl'
104 | end
105 |
106 | # require all authentication & authorization related types
107 | %i[
108 | jenkins_user
109 | jenkins_security_realm
110 | jenkins_authorization_strategy
111 | ].each do |type|
112 | autorequire(type) do
113 | catalog.resources.select do |r|
114 | r.is_a?(Puppet::Type.type(type))
115 | end
116 | end
117 | end
118 | end
119 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_job.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'puppet/property/boolean'
4 | require 'puppet/parameter/boolean'
5 | require 'puppet/util/diff'
6 | require 'puppet/util/checksums'
7 | require 'pathname'
8 | require 'tempfile'
9 |
10 | require_relative '../../puppet/x/jenkins/type/cli'
11 |
12 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_job) do
13 | @doc = "Manage Jenkins' jobs"
14 |
15 | ensurable
16 |
17 | newparam(:name) do
18 | desc 'job name'
19 | isnamevar
20 | end
21 |
22 | newproperty(:config) do
23 | include Puppet::Util::Diff
24 | include Puppet::Util::Checksums
25 |
26 | desc 'XML job configuration string'
27 |
28 | def change_to_s(currentvalue, newvalue)
29 | if currentvalue == :absent
30 | 'created'
31 | elsif newvalue == :absent
32 | 'removed'
33 | else
34 | return 'left unchanged' if @resource[:replace] == false
35 |
36 | if Puppet[:show_diff] && resource[:show_diff]
37 | # XXX this really should be turned into a helper method and submitted
38 | # to # core puppet
39 | Tempfile.open('puppet-file') do |d1|
40 | d1.write(currentvalue)
41 | d1.flush
42 | Tempfile.open('puppet-file') do |d2|
43 | d2.write(newvalue)
44 | d2.flush
45 |
46 | send @resource[:loglevel], "\n#{diff(d1.path, d2.path)}"
47 |
48 | d2.close
49 | d2.unlink
50 | end
51 | d1.close
52 | d1.unlink
53 | end
54 |
55 | end
56 | "content changed '{md5}#{md5(currentvalue)}' to '{md5}#{md5(newvalue)}'"
57 | end
58 | end
59 | end
60 |
61 | newparam(:show_diff, boolean: true, parent: Puppet::Parameter::Boolean) do
62 | desc 'enable/disable displaying configuration diff'
63 | defaultto true
64 | end
65 |
66 | newproperty(:enable, boolean: true, parent: Puppet::Property::Boolean) do
67 | desc 'enable/disable job'
68 | defaultto true
69 | end
70 |
71 | newparam(:replace, boolean: true, parent: Puppet::Parameter::Boolean) do
72 | desc 'replace existing job'
73 | defaultto true
74 | end
75 |
76 | # require all authentication & authorization related types
77 | %i[
78 | jenkins_user
79 | jenkins_security_realm
80 | jenkins_authorization_strategy
81 | ].each do |type|
82 | autorequire(type) do
83 | catalog.resources.select do |r|
84 | r.is_a?(Puppet::Type.type(type))
85 | end
86 | end
87 | end
88 |
89 | # if the job is contained in a `cloudbees-folder`, autorequire any parent
90 | # folder jobs
91 | # XXX we can't inspect @resource[:name] or self[:name] here outside of teh
92 | # autorequire block because of meta-programming funkiness
93 | autorequire(:jenkins_job) do
94 | if self[:ensure] == :present
95 | folders = []
96 | Pathname(self[:name]).dirname.descend { |d| folders << d.to_path }
97 | folders
98 | end
99 | end
100 |
101 | # XXX completely punting on handling delete ordering for puppet < 4
102 | unless Puppet.version.to_f < 4.0
103 | autobefore(:jenkins_job) do
104 | if self[:ensure] == :absent
105 | folders = []
106 | Pathname(self[:name]).dirname.descend { |d| folders << d.to_path }
107 | folders
108 | end
109 | end
110 | end
111 | end
112 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_num_executors.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../puppet/x/jenkins/type/cli'
4 |
5 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_num_executors) do
6 | @doc = "Manage Jenkins' number of executor slots"
7 |
8 | # the cli jar does not have an interface for plugin removal so the only
9 | # allowed ensure value is :present
10 | ensurable do
11 | newvalue(:present) { provider.create }
12 | end
13 |
14 | newparam(:name) do
15 | desc 'Number of executors'
16 | isnamevar
17 |
18 | munge do |value|
19 | if value.is_a?(String) && value =~ %r{^[0-9]+$}
20 | Integer(value)
21 | else
22 | value
23 | end
24 | end
25 | end
26 |
27 | # require all authentication & authorization related types
28 | %i[
29 | jenkins_user
30 | jenkins_security_realm
31 | jenkins_authorization_strategy
32 | ].each do |type|
33 | autorequire(type) do
34 | catalog.resources.select do |r|
35 | r.is_a?(Puppet::Type.type(type))
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_security_realm.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../puppet/x/jenkins/type/cli'
4 |
5 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_security_realm) do
6 | @doc = "Manage Jenkins' security realm"
7 |
8 | ensurable
9 |
10 | newparam(:name) do
11 | desc 'Name of the security realm class'
12 | isnamevar
13 | end
14 |
15 | newproperty(:arguments, array_matching: :all) do
16 | desc 'List of arguments to security realm class constructor'
17 | end
18 |
19 | # require all instances of jenkins_user, as does
20 | # jenkins_authorization_strategy, to ensure that the state of jenkins_user
21 | # resources is not attempted to be modify between jenkins_security_realm and
22 | # jenkins_authorization_strategy state changes.
23 | autorequire(:jenkins_user) do
24 | catalog.resources.select do |r|
25 | r.is_a?(Puppet::Type.type(:jenkins_user))
26 | end
27 | end
28 |
29 | autorequire(:jenkins_authorization_strategy) do
30 | if self[:ensure] == :absent
31 | catalog.resources.select do |r|
32 | r.is_a?(Puppet::Type.type(:jenkins_authorization_strategy))
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_slaveagent_port.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../puppet/x/jenkins/type/cli'
4 |
5 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_slaveagent_port) do
6 | @doc = "Manage Jenkins' slave agent listening port"
7 |
8 | # the cli jar does not have an interface for plugin removal so the only
9 | # allowed ensure value is :present
10 | ensurable do
11 | newvalue(:present) { provider.create }
12 | end
13 |
14 | newparam(:name) do
15 | desc 'port number'
16 | isnamevar
17 |
18 | munge do |value|
19 | if value.is_a?(String) && value =~ %r{^[0-9]+$}
20 | Integer(value)
21 | else
22 | value
23 | end
24 | end
25 | end
26 |
27 | # require all authentication & authorization related types
28 | %i[
29 | jenkins_user
30 | jenkins_security_realm
31 | jenkins_authorization_strategy
32 | ].each do |type|
33 | autorequire(type) do
34 | catalog.resources.select do |r|
35 | r.is_a?(Puppet::Type.type(type))
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/puppet/type/jenkins_user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../puppet/x/jenkins/type/cli'
4 |
5 | Puppet::X::Jenkins::Type::Cli.newtype(:jenkins_user) do
6 | @doc = "Manage Jenkins' user account information"
7 |
8 | ensurable
9 |
10 | newparam(:name) do
11 | desc "Account login name. Jenkins calls this 'id'"
12 | isnamevar
13 | end
14 |
15 | newproperty(:full_name) do
16 | desc 'Optional longer account name.'
17 | end
18 |
19 | newproperty(:email_address) do
20 | desc 'email address'
21 | end
22 |
23 | newproperty(:api_token_plain) do
24 | desc "Unhashed or 'plain_text' API token that is digested to produce the public API token"
25 | validate do |value|
26 | # 32 char hex string
27 | unless value =~ %r{^\h{32}$}
28 | raise ArgumentError, "#{value} is not a 32char hex string"
29 | end
30 | end
31 | end
32 |
33 | newproperty(:api_token_public) do
34 | # XXX validate
35 | desc 'Literal public API token. read-only property.'
36 | end
37 |
38 | newproperty(:public_keys, array_matching: :all) do
39 | desc 'Array of ssh public key strings'
40 | end
41 |
42 | newproperty(:password) do
43 | desc 'Password for HudsonPrivateSecurityRealm'
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/puppet/x/jenkins.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Puppet::X; end
4 |
5 | module Puppet::X::Jenkins; end
6 |
--------------------------------------------------------------------------------
/lib/puppet/x/jenkins/config.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'facter'
4 |
5 | require_relative '../jenkins'
6 |
7 | require 'puppet/util/warnings'
8 |
9 | # This class is used to lookup common configuration values by first looking for
10 | # the desired key as parameter to the config class in the catalog, then
11 | # checking for a prefixed fact, and falling back to hard coded defaults.
12 | class Puppet::X::Jenkins::Config
13 | class UnknownConfig < ArgumentError; end
14 |
15 | DEFAULTS = {
16 | cli_jar: '/usr/share/java/jenkins-cli.jar',
17 | url: 'http://localhost:8080',
18 | ssh_private_key: nil,
19 | puppet_helper: '/usr/share/java/puppet_helper.groovy',
20 | cli_tries: 30,
21 | cli_username: nil,
22 | cli_password: nil,
23 | cli_password_file: '/tmp/jenkins_credentials_for_puppet',
24 | cli_password_file_exists: false
25 | }.freeze
26 | CONFIG_CLASS = 'jenkins::cli::config'
27 | FACT_PREFIX = 'jenkins_'
28 |
29 | def initialize(catalog = nil)
30 | @catalog = catalog
31 | end
32 |
33 | def [](key)
34 | key = key.to_sym
35 | raise UnknownConfig unless DEFAULTS.key?(key)
36 |
37 | value = catalog_lookup(key) || fact_lookup(key) || default_lookup(key)
38 | return if value.nil?
39 |
40 | Puppet::Util::Warnings.debug_once "config: #{key} = #{value}"
41 |
42 | # handle puppet 3.x passing in all values as strings and convert back to
43 | # Integer/Fixnum
44 | if Puppet.version =~ %r{^3}
45 | default_type_integer?(key) ? value.to_i : value
46 | else
47 | value
48 | end
49 | end
50 |
51 | def catalog_lookup(key)
52 | return nil if @catalog.nil?
53 |
54 | config = @catalog.resource(:class, CONFIG_CLASS)
55 | return nil if config.nil?
56 |
57 | config[key.to_sym]
58 | end
59 |
60 | def fact_lookup(key)
61 | fact = FACT_PREFIX + key.to_s
62 | Facter.value(fact.to_sym)
63 | end
64 |
65 | def default_lookup(key)
66 | DEFAULTS[key]
67 | end
68 |
69 | def default_type_integer?(key)
70 | DEFAULTS[key].is_a?(Integer)
71 | end
72 | end
73 |
--------------------------------------------------------------------------------
/lib/puppet/x/jenkins/provider.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../jenkins'
4 |
5 | module Puppet::X::Jenkins::Provider; end
6 |
--------------------------------------------------------------------------------
/lib/puppet/x/jenkins/type.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../jenkins'
4 |
5 | module Puppet::X::Jenkins::Type; end
6 |
--------------------------------------------------------------------------------
/lib/puppet/x/jenkins/type/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../jenkins/type'
4 | require_relative '../../jenkins/config'
5 |
6 | module Puppet::X::Jenkins::Type::Cli
7 | def self.newtype(*args, &block)
8 | type = Puppet::Type.newtype(*args, &block)
9 |
10 | # The jenkins master needs to be avaiable in order to interact with it via
11 | # the cli jar.
12 | type.autorequire(:service) do
13 | ['jenkins']
14 | end
15 |
16 | # If a file resource is declared for file path params, make sure that it's
17 | # converged so we can read it off disk.
18 | type.autorequire(:file) do
19 | config = Puppet::X::Jenkins::Config.new(catalog)
20 |
21 | autos = []
22 | %w[ssh_private_key puppet_helper cli_jar].each do |param|
23 | value = config[param.to_sym]
24 | autos << value unless value.nil?
25 | end
26 |
27 | autos
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/puppet/x/jenkins/util.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../jenkins'
4 |
5 | module Puppet::X::Jenkins::Util
6 | def unundef(data)
7 | iterate(data) { |x| x == :undef ? nil : x }
8 | end
9 | module_function :unundef
10 |
11 | def undefize(data)
12 | iterate(data) { |x| x.nil? ? :undef : x }
13 | end
14 | module_function :undefize
15 |
16 | # loosely based on
17 | # https://stackoverflow.com/questions/16412013/iterate-nested-hash-that-contains-hash-and-or-array
18 | def iterate(data, &block)
19 | return data unless block_given?
20 |
21 | case data
22 | when Hash
23 | data.transform_values do |v|
24 | iterate(v, &block)
25 | end
26 | when Array
27 | data.map { |v| iterate(v, &block) }
28 | else
29 | yield data
30 | end
31 | end
32 | module_function :iterate
33 | end
34 |
--------------------------------------------------------------------------------
/manifests/augeas.pp:
--------------------------------------------------------------------------------
1 | # @summary Change config files using augeas
2 | #
3 | # @param config_filename
4 | # Filename of the configuration file to work on relative to the jenkins
5 | # localstatedir.
6 | #
7 | # @param changes
8 | # String or array with augeas changes to perform.
9 | #
10 | # @param onlyif
11 | # Optional augeas command and comparisons to control the execution of this type.
12 | #
13 | # @param plugin
14 | # Optionally jenkins::augeas can also install the plugin. If this is set to
15 | # true, we use the name of the resource as plugin name. If it's a string,
16 | # that is used as plugin name.
17 | #
18 | # @param plugin_version
19 | # Optional plugin version to pass through to jenkins::plugin
20 | #
21 | # @param context
22 | # Optional context to ease your change rules.
23 | #
24 | # @param restart
25 | # If set to true, will trigger a jenkins (safe-)restart in stead of reloading
26 | # the configuration.
27 | #
28 | # @param show_diff
29 | # Whether to display differences when the file changes, defaulting to true.
30 | #
31 | # @example Configure the git plugin
32 | # jenkins::augeas { 'git':
33 | # plugin => true,
34 | # config_filename => 'hudson.plugins.git.GitSCM.xml',
35 | # context => '/hudson.plugins.git.GitSCM_-DescriptorImpl',
36 | # changes => [
37 | # 'set globalConfigName/#text "Bob the Builder"',
38 | # 'set globalConfigEmail/#text "bob@example.com",
39 | # ],
40 | # }
41 | define jenkins::augeas (
42 | String $config_filename,
43 | Variant[Array[String], String] $changes,
44 | Optional[Variant[Array[String], String]] $onlyif = undef,
45 | Optional[String] $plugin_version = undef,
46 | String $context = '/',
47 | Variant[Boolean,String] $plugin = false,
48 | Boolean $restart = false,
49 | Boolean $show_diff = true,
50 | ) {
51 | include jenkins
52 | include jenkins::cli
53 |
54 | case $plugin {
55 | true: {
56 | jenkins::plugin { $name:
57 | version => $plugin_version,
58 | before => Augeas["jenkins::augeas: ${name}"],
59 | }
60 | }
61 | false: {
62 | # do nothing
63 | }
64 | default: {
65 | jenkins::plugin { $plugin:
66 | version => $plugin_version,
67 | before => Augeas["jenkins::augeas: ${name}"],
68 | }
69 | }
70 | }
71 |
72 | if $restart {
73 | $notify_exec = 'safe-restart-jenkins'
74 | } else {
75 | $notify_exec = 'reload-jenkins'
76 | }
77 |
78 | augeas { "jenkins::augeas: ${name}":
79 | incl => "${jenkins::localstatedir}/${config_filename}",
80 | lens => 'Xml.lns',
81 | context => regsubst("/files${jenkins::localstatedir}/${config_filename}/${context}", '\/{2,}', '/', 'G'),
82 | notify => Exec[$notify_exec],
83 | onlyif => $onlyif,
84 | changes => $changes,
85 | show_diff => $show_diff,
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/manifests/cli.pp:
--------------------------------------------------------------------------------
1 | # @summary Allow Jenkins commands to be issued from the command line
2 | # @api private
3 | class jenkins::cli {
4 | assert_private()
5 |
6 | include jenkins
7 |
8 | # XXX Classes/defines which include the jenkins::cli class assume that they
9 | # can use the cli even if $jenkins::cli == false. This breaks the top
10 | # level anchor pattern. The cli param should either be deprecated and
11 | # essentially hardwired to true or attempting to use cli functionality
12 | # without this param set should fail; either option is a backwards
13 | # incompatible change.
14 | #
15 | # As an attempt to preserve backwards compatibility, there are includes and
16 | # resource relationships being scattered throughout this module.
17 | if $jenkins::manage_service {
18 | Class['jenkins::service']
19 | -> Class['jenkins::cli']
20 | -> Anchor['jenkins::end']
21 | }
22 |
23 | $jar = "${jenkins::libdir}/jenkins-cli.jar"
24 | $extract_jar = "jar -xf ${jenkins::libdir}/jenkins.war WEB-INF/lib/"
25 | $move_jar = "mv WEB-INF/lib/cli-*.jar ${jar}"
26 | $remove_dir = 'rm -rf WEB-INF'
27 | $cli_tries = $jenkins::cli_tries
28 | $cli_try_sleep = $jenkins::cli_try_sleep
29 |
30 | # make sure we always call Exec[jenlins-cli] in case
31 | # the binary does not exist
32 | exec { 'check-jenkins-cli':
33 | command => '/bin/true',
34 | creates => $jar,
35 | }
36 | ~> exec { 'jenkins-cli' :
37 | command => "${extract_jar} && ${move_jar} && ${remove_dir}",
38 | path => ['/bin', '/usr/bin'],
39 | cwd => '/tmp',
40 | refreshonly => true,
41 | }
42 | # Extract latest CLI in case package is updated / downgraded
43 | Package[$jenkins::package_name] ~> Exec['jenkins-cli']
44 |
45 | file { $jar:
46 | ensure => file,
47 | mode => '0644',
48 | require => Exec['jenkins-cli'],
49 | }
50 |
51 | $port = jenkins_port()
52 | $prefix = jenkins_prefix()
53 |
54 | # The jenkins cli command with required parameter(s)
55 | $cmd = join(
56 | delete_undef_values([
57 | 'java',
58 | "-jar ${jar}",
59 | "-s http://localhost:${port}${prefix}",
60 | $jenkins::_cli_auth_arg,
61 | ]),
62 | ' '
63 | )
64 |
65 | # Do a safe restart of Jenkins (only when notified)
66 | exec { 'safe-restart-jenkins':
67 | command => "${cmd} safe-restart && /bin/sleep 10",
68 | path => ['/bin', '/usr/bin'],
69 | tries => $cli_tries,
70 | try_sleep => $cli_try_sleep,
71 | refreshonly => true,
72 | require => File[$jar],
73 | }
74 |
75 | # jenkins::cli::reload should be included only after $jenkins::cli::cmd is
76 | # defined
77 | include jenkins::cli::reload
78 | }
79 |
--------------------------------------------------------------------------------
/manifests/cli/config.pp:
--------------------------------------------------------------------------------
1 | # This class provides configuration values to override defaults and fact data
2 | # for PuppetX::Jenkins::Provider::Clihelper based providers.
3 | #
4 | # Default and fact data is managed internal to the
5 | # PuppetX::Jenkins::Provider::Clihelper class for compatiblity with the puppet
6 | # resource face. No defaults should be set in this classes definition.
7 | class jenkins::cli::config (
8 | Optional[Stdlib::Absolutepath] $cli_jar = undef,
9 | Optional[String] $url = undef,
10 | Optional[Stdlib::Absolutepath] $ssh_private_key = undef,
11 | Optional[Stdlib::Absolutepath] $puppet_helper = undef,
12 | Optional[Integer] $cli_tries = undef,
13 | Optional[Numeric] $cli_try_sleep = undef,
14 | Optional[String] $cli_username = undef,
15 | Optional[String] $cli_password = undef,
16 | String $cli_password_file = '/tmp/jenkins_credentials_for_puppet',
17 | Boolean $cli_password_file_exists = false,
18 | Optional[String] $ssh_private_key_content = undef,
19 | ) {
20 | # lint:ignore:legacy_facts
21 | $is_root = $facts['id'] == 'root'
22 | # lint:endignore
23 |
24 | if $ssh_private_key and $ssh_private_key_content {
25 | file { $ssh_private_key:
26 | ensure => 'file',
27 | mode => '0400',
28 | backup => false,
29 | content => $ssh_private_key_content,
30 | }
31 |
32 | # allow this class to be included when not running as root
33 | if $is_root {
34 | File[$ssh_private_key] {
35 | # the owner/group should probably be set externally and retrieved if
36 | # present in the manfiest. At present, there is no authoritative place
37 | # to retrive this information from.
38 | owner => 'jenkins',
39 | group => 'jenkins',
40 | }
41 | }
42 | }
43 |
44 | # We manage the password file, to avoid printing username/password in the
45 | # ps ax output.
46 | # If file exists, we assume the user manages permissions and content
47 | if $cli_username and $cli_password and !$cli_password_file_exists {
48 | file { $cli_password_file:
49 | ensure => 'file',
50 | mode => '0400',
51 | backup => false,
52 | content => "${cli_username}:${cli_password}",
53 | }
54 |
55 | # allow this class to be included when not running as root
56 | if $is_root {
57 | File[$cli_password_file] {
58 | # the owner/group should probably be set externally and retrieved if
59 | # present in the manfiest. At present, there is no authoritative place
60 | # to retrive this information from.
61 | owner => 'jenkins',
62 | group => 'jenkins',
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/manifests/cli/exec.pp:
--------------------------------------------------------------------------------
1 | # @summary Executing custom helper script commands via the Jenkins CLI.
2 | #
3 | # @param unless
4 | # The unless parameter passed to the exec resource
5 | # @param command
6 | # The command or commands to run
7 | define jenkins::cli::exec (
8 | Optional[String] $unless = undef,
9 | Variant[String, Array] $command = $title,
10 | ) {
11 | include jenkins
12 | include jenkins::cli_helper
13 | include jenkins::cli::reload
14 |
15 | Class['jenkins::cli_helper']
16 | -> Jenkins::Cli::Exec[$title]
17 | -> Anchor['jenkins::end']
18 |
19 | # $command may be either a string or an array due to the use of flatten()
20 | $run = join(
21 | delete_undef_values(
22 | flatten([
23 | $jenkins::cli_helper::helper_cmd,
24 | $command,
25 | ])
26 | ),
27 | ' '
28 | )
29 |
30 | if $unless {
31 | $environment_run = ["HELPER_CMD=eval ${jenkins::cli_helper::helper_cmd}"]
32 | } else {
33 | $environment_run = undef
34 | }
35 |
36 | exec { $title:
37 | provider => 'shell',
38 | command => $run,
39 | environment => $environment_run,
40 | unless => $unless,
41 | tries => $jenkins::cli_tries,
42 | try_sleep => $jenkins::cli_try_sleep,
43 | notify => Class['jenkins::cli::reload'],
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/manifests/cli/reload.pp:
--------------------------------------------------------------------------------
1 | # @summary Command Jenkins to reload config.xml via the CLI.
2 | # @api private
3 | class jenkins::cli::reload {
4 | assert_private()
5 |
6 | $cli_tries = $jenkins::cli_tries
7 | $cli_try_sleep = $jenkins::cli_try_sleep
8 | $jar_file = $jenkins::cli::jar
9 |
10 | # Reload all Jenkins config from disk (only when notified)
11 | exec { 'reload-jenkins':
12 | command => "${jenkins::cli::cmd} reload-configuration",
13 | path => ['/bin', '/usr/bin'],
14 | tries => $cli_tries,
15 | try_sleep => $cli_try_sleep,
16 | refreshonly => true,
17 | require => File[$jar_file],
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/manifests/cli_helper.pp:
--------------------------------------------------------------------------------
1 | # @summary A helper script for creating resources via the Jenkins cli
2 | class jenkins::cli_helper {
3 | include jenkins
4 | include jenkins::cli
5 |
6 | Class['jenkins::cli']
7 | -> Class['jenkins::cli_helper']
8 | -> Anchor['jenkins::end']
9 |
10 | $libdir = $jenkins::libdir
11 | $cli_jar = $jenkins::cli::jar
12 | $port = jenkins_port()
13 | $prefix = jenkins_prefix()
14 | $helper_groovy = "${libdir}/puppet_helper.groovy"
15 |
16 | file { $helper_groovy:
17 | source => 'puppet:///modules/jenkins/puppet_helper.groovy',
18 | owner => $jenkins::user,
19 | group => $jenkins::group,
20 | mode => '0444',
21 | require => Class['jenkins::cli'],
22 | }
23 |
24 | $helper_cmd = join(
25 | delete_undef_values([
26 | '/bin/cat',
27 | $helper_groovy,
28 | '|',
29 | '/usr/bin/java',
30 | "-jar ${cli_jar}",
31 | "-s http://127.0.0.1:${port}${prefix}",
32 | $jenkins::_cli_auth_arg,
33 | 'groovy =',
34 | ]),
35 | ' '
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/manifests/config.pp:
--------------------------------------------------------------------------------
1 | # @summary Wire up the configuration
2 | # @api private
3 | class jenkins::config {
4 | assert_private()
5 |
6 | ensure_resource('jenkins::plugin', $jenkins::default_plugins)
7 | }
8 |
--------------------------------------------------------------------------------
/manifests/credentials.pp:
--------------------------------------------------------------------------------
1 | # Copyright 2014 RetailMeNot, Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # @summary Jenkins credentials via the CloudBees Credentials plugin
16 | define jenkins::credentials (
17 | String $password,
18 | String $description = 'Managed by Puppet',
19 | String $private_key_or_path = '', # lint:ignore:params_empty_string_assignment
20 | Enum['present', 'absent'] $ensure = 'present',
21 | String $uuid = '', # lint:ignore:params_empty_string_assignment
22 | ) {
23 | include jenkins
24 | include jenkins::cli_helper
25 |
26 | Class['jenkins::cli_helper']
27 | -> Jenkins::Credentials[$title]
28 | -> Anchor['jenkins::end']
29 |
30 | case $ensure {
31 | 'present': {
32 | jenkins::cli::exec { "create-jenkins-credentials-${title}":
33 | command => [
34 | 'create_or_update_credentials',
35 | $title,
36 | "'${password}'",
37 | "'${uuid}'",
38 | "'${description}'",
39 | "'${private_key_or_path}'",
40 | ],
41 | unless => "for i in \$(seq 1 ${jenkins::cli_tries}); do \$HELPER_CMD credential_info ${title} && break || sleep ${jenkins::cli_try_sleep}; done | grep ${title}", # lint:ignore:140chars
42 | }
43 | }
44 | 'absent': {
45 | # XXX not idempotent
46 | jenkins::cli::exec { "delete-jenkins-credentials-${title}":
47 | command => [
48 | 'delete_credentials',
49 | $title,
50 | ],
51 | }
52 | }
53 | default: {
54 | fail "ensure must be 'present' or 'absent' but '${ensure}' was given"
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/manifests/direct_download.pp:
--------------------------------------------------------------------------------
1 | # @summary Support for directly downloading a package file - for when no
2 | # repository is available
3 | # @api private
4 | class jenkins::direct_download {
5 | assert_private()
6 |
7 | include jenkins::proxy
8 |
9 | # directory for temp files
10 | file { $jenkins::package_cache_dir:
11 | ensure => directory,
12 | owner => 'root',
13 | group => 'root',
14 | mode => '0644',
15 | }
16 |
17 | # equivalent to basename() - get the filename
18 | $package_file = regsubst($jenkins::direct_download, '(.*?)([^/]+)$', '\2')
19 | $local_file = "${jenkins::package_cache_dir}/${package_file}"
20 |
21 | if $jenkins::version != 'absent' {
22 | # make download optional if we are removing...
23 | archive { $package_file:
24 | source => $jenkins::direct_download,
25 | path => $local_file,
26 | proxy_server => $jenkins::proxy::url,
27 | cleanup => false,
28 | extract => false,
29 | before => Package[$jenkins::package_name],
30 | }
31 | }
32 |
33 | package { $jenkins::package_name:
34 | ensure => $jenkins::version,
35 | provider => $jenkins::package_provider,
36 | source => $local_file,
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/manifests/firewall.pp:
--------------------------------------------------------------------------------
1 | # @summary Integrate with the puppetlabs-firewall module for opening the port
2 | # to Jenkins automatically
3 | # @api private
4 | class jenkins::firewall {
5 | assert_private()
6 |
7 | firewall { '500 allow Jenkins inbound traffic':
8 | action => 'accept',
9 | state => 'NEW',
10 | dport => [jenkins_port()],
11 | proto => 'tcp',
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/manifests/job.pp:
--------------------------------------------------------------------------------
1 | # @summary Manage Jenkins jobs given a name and config xml
2 | #
3 | # @param config The content of the jenkins job config file (required)
4 | # @param source Path to a puppet file() resource containing the Jenkins XML job description.
5 | # Will override 'config' if set
6 | # @param template Path to a puppet template() resource containing the Jenkins XML job description.
7 | # Will override 'config' if set
8 | # @param jobname the name of the jenkins job
9 | # @param ensure choose 'absent' to ensure the job is removed
10 | # @param difftool Provide a command to execute to compare Jenkins job files
11 | # @param replace
12 | # Whether or not to replace the job if it already exists.
13 | define jenkins::job (
14 | String $config,
15 | Optional[String] $source = undef,
16 | Optional[String[1]] $template = undef,
17 | String $jobname = $title,
18 | Enum['present', 'absent'] $ensure = 'present',
19 | String $difftool = '/usr/bin/diff -b -q',
20 | Boolean $replace = true
21 | ) {
22 | include jenkins::cli
23 |
24 | Class['jenkins::cli']
25 | -> Jenkins::Job[$title]
26 | -> Anchor['jenkins::end']
27 |
28 | if ($ensure == 'absent') {
29 | jenkins::job::absent { $title:
30 | jobname => $jobname,
31 | }
32 | } else {
33 | if $source {
34 | $realconfig = file($source)
35 | }
36 | elsif $template {
37 | $realconfig = template($template)
38 | }
39 | else {
40 | $realconfig = $config
41 | }
42 |
43 | jenkins::job::present { $title:
44 | config => $realconfig,
45 | jobname => $jobname,
46 | difftool => $difftool,
47 | replace => $replace,
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/manifests/job/absent.pp:
--------------------------------------------------------------------------------
1 | # @summary Removes a jenkins build job
2 | # @api private
3 | #
4 | # @param jobname
5 | # the name of the jenkins job
6 | #
7 | define jenkins::job::absent (
8 | String $jobname = $title,
9 | ) {
10 | include jenkins::cli
11 |
12 | if $jenkins::service_ensure == 'stopped' or $jenkins::service_ensure == false {
13 | fail('Management of Jenkins jobs requires \$jenkins::service_ensure to be set to \'running\'')
14 | }
15 |
16 | $tmp_config_path = "/tmp/${jobname}-config.xml"
17 | $job_dir = "${jenkins::job_dir}/${jobname}"
18 | $config_path = "${job_dir}/config.xml"
19 |
20 | # Temp file to use as stdin for Jenkins CLI executable
21 | file { $tmp_config_path:
22 | ensure => absent,
23 | }
24 |
25 | # Delete the job
26 | exec { "jenkins delete-job ${jobname}":
27 | path => ['/usr/bin', '/usr/sbin', '/bin'],
28 | command => "${jenkins::cli::cmd} delete-job \"${jobname}\"",
29 | logoutput => false,
30 | onlyif => "test -f \"${config_path}\"",
31 | require => Exec['jenkins-cli'],
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/manifests/job/present.pp:
--------------------------------------------------------------------------------
1 | # @summary Creates or updates a jenkins build job
2 | # @api private
3 | #
4 | # @param config The content of the jenkins job config file
5 | # @param config_file Jenkins job config file (file on disk)
6 | # @param jobname The name of the jenkins job
7 | # @param replace Whether or not to replace the job if it already exists.
8 | #
9 | define jenkins::job::present (
10 | Optional[String] $config = undef,
11 | Optional[String] $config_file = undef,
12 | String $jobname = $title,
13 | String $difftool = '/usr/bin/diff -b -q',
14 | Boolean $replace = true,
15 | ) {
16 | include jenkins::cli
17 | include jenkins::cli::reload
18 |
19 | if $config_file and $config {
20 | fail('You cannot set both $config_file AND $config param, only one is required')
21 | }
22 |
23 | if $config_file == undef and $config == undef {
24 | fail('Please set one of $config_file or $config to create a job')
25 | }
26 |
27 | if $jenkins::service_ensure == 'stopped' or $jenkins::service_ensure == false {
28 | fail('Management of Jenkins jobs requires \$jenkins::service_ensure to be set to \'running\'')
29 | }
30 |
31 | $jenkins_cli = $jenkins::cli::cmd
32 | if $config == undef {
33 | $tmp_config_path = $config_file
34 | }
35 | else {
36 | $tmp_config_path = "/tmp/${jobname}-config.xml"
37 | #
38 | # When a Jenkins job is imported via the cli, Jenkins will
39 | # re-format the xml file based on its own internal rules.
40 | # In order to make job management idempotent, we need to
41 | # apply that formatting before the import, so we can do a diff
42 | # on any pre-existing job to determine if an update is needed.
43 | #
44 | # Jenkins likes to change single quotes to double quotes
45 | $a = regsubst($config, 'version=\'1.0\' encoding=\'UTF-8\'',
46 | 'version="1.0" encoding="UTF-8"')
47 | # Change empty tags into self-closing tags
48 | $b = regsubst($a, '<([A-z]+)><\/\1>', '<\1/>', 'IG')
49 | # Change " to " since Jenkins is weird like that
50 | $c = regsubst($b, '"', '"', 'MG')
51 | # Change ' to ' since Jenkins is weird like that
52 | $d = regsubst($c, ''', '\'', 'MG')
53 |
54 | # Temp file to use as stdin for Jenkins CLI executable
55 | file { $tmp_config_path:
56 | content => $d,
57 | require => Exec['jenkins-cli'],
58 | before => Exec["jenkins create-job ${jobname}"],
59 | }
60 | }
61 |
62 | $job_dir = "${jenkins::job_dir}/${jobname}"
63 | $config_path = "${job_dir}/config.xml"
64 |
65 | # Bring variables from Class['jenkins'] into local scope.
66 | $cli_tries = $jenkins::cli_tries
67 | $cli_try_sleep = $jenkins::cli_try_sleep
68 |
69 | Exec {
70 | logoutput => false,
71 | path => '/bin:/usr/bin:/sbin:/usr/sbin',
72 | tries => $cli_tries,
73 | try_sleep => $cli_try_sleep,
74 | }
75 |
76 | # Use Jenkins CLI to create the job
77 | $cat_config = "cat \"${tmp_config_path}\""
78 | $create_job = "${jenkins_cli} create-job \"${jobname}\""
79 | exec { "jenkins create-job ${jobname}":
80 | command => "${cat_config} | ${create_job}",
81 | creates => [$config_path, "${job_dir}/builds"],
82 | }
83 |
84 | if $replace {
85 | # Use Jenkins CLI to update the job if it already exists
86 | $update_job = "${jenkins_cli} update-job ${jobname}"
87 | exec { "jenkins update-job ${jobname}":
88 | command => "${cat_config} | ${update_job}",
89 | onlyif => "test -e ${config_path}",
90 | unless => "${difftool} ${config_path} ${tmp_config_path}",
91 | notify => Exec['reload-jenkins'],
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/manifests/jobs.pp:
--------------------------------------------------------------------------------
1 | # @summary Create Jenkins Jobs
2 | # @api private
3 | class jenkins::jobs {
4 | assert_private()
5 |
6 | create_resources('jenkins::job', $jenkins::job_hash)
7 | }
8 |
--------------------------------------------------------------------------------
/manifests/master.pp:
--------------------------------------------------------------------------------
1 | # @summary Install a master
2 | #
3 | # @param version
4 | # Version of the swarm plugin
5 | class jenkins::master (
6 | String $version = $jenkins::params::swarm_version
7 | ) inherits jenkins::params {
8 | jenkins::plugin { 'swarm':
9 | version => $version,
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/manifests/package.pp:
--------------------------------------------------------------------------------
1 | # @summary Installation of the Jenkins native package.
2 | #
3 | # The package might not specify a dependency on Java, so you may need to
4 | # specify that yourself
5 | #
6 | # @api private
7 | class jenkins::package {
8 | assert_private()
9 |
10 | package { $jenkins::package_name:
11 | ensure => $jenkins::version,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/manifests/params.pp:
--------------------------------------------------------------------------------
1 | # @summary Default parameters
2 | # @api private
3 | class jenkins::params {
4 | $swarm_version = '2.2'
5 | $config_hash_defaults = {
6 | 'JAVA_OPTS' => { value => '-Djava.awt.headless=true -Djenkins.install.runSetupWizard=false' },
7 | }
8 | $default_plugins = [
9 | 'bouncycastle-api', # required by instance-identity
10 | 'credentials', # required by puppet_helper.groovy
11 | 'instance-identity', # implied by structs
12 | 'javax-activation-api', # implied by all plugin
13 | 'javax-mail-api', # implied by all plugins
14 | 'structs', # required by credentials plugin
15 | ]
16 |
17 | case $facts['os']['family'] {
18 | 'Debian': {
19 | $repo = true
20 | $package_provider = 'dpkg'
21 | }
22 | 'RedHat': {
23 | $repo = true
24 | $package_provider = 'rpm'
25 | }
26 | 'Archlinux': {
27 | $repo = false
28 | $package_provider = 'pacman'
29 | }
30 | default: {
31 | $repo = true
32 | $package_provider = undef
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/manifests/plugins.pp:
--------------------------------------------------------------------------------
1 | # @summary Install Jenkins plugins
2 | # @api private
3 | class jenkins::plugins {
4 | assert_private()
5 |
6 | create_resources('jenkins::plugin',$jenkins::plugin_hash)
7 | }
8 |
--------------------------------------------------------------------------------
/manifests/proxy.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure the proxy part
2 | # @api private
3 | class jenkins::proxy {
4 | assert_private()
5 |
6 | # Bring variables from Class['jenkins'] into local scope.
7 | $proxy_host = $jenkins::proxy_host
8 | $proxy_port = $jenkins::proxy_port
9 | $no_proxy_list = $jenkins::no_proxy_list
10 |
11 | if $proxy_host and $proxy_port {
12 | # param format needed by puppet/archive
13 | $url = "http://${proxy_host}:${proxy_port}"
14 | $proxy_xml = "${jenkins::localstatedir}/proxy.xml"
15 |
16 | file { $proxy_xml:
17 | content => template('jenkins/proxy.xml.erb'),
18 | owner => $jenkins::user,
19 | group => $jenkins::group,
20 | mode => '0644',
21 | }
22 |
23 | Package['jenkins']
24 | -> File[$proxy_xml]
25 | ~> Class['jenkins::service']
26 | } else {
27 | $url = undef
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/manifests/repo.pp:
--------------------------------------------------------------------------------
1 | # @summary Pull in the platform specific repo classes
2 | # @api private
3 | class jenkins::repo (
4 | Stdlib::Httpurl $base_url = 'https://pkg.jenkins.io',
5 | String $gpg_key_filename = 'jenkins.io-2023.key',
6 | Boolean $enabled = true,
7 | ) {
8 | assert_private()
9 |
10 | if $jenkins::repo {
11 | case $facts['os']['family'] {
12 | 'RedHat', 'Linux': {
13 | contain jenkins::repo::el
14 | }
15 |
16 | 'Debian': {
17 | contain jenkins::repo::debian
18 | }
19 |
20 | 'Suse' : {
21 | contain jenkins::repo::suse
22 | }
23 |
24 | default: {
25 | fail( "Unsupported OS family: ${facts['os']['family']}" )
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/manifests/repo/debian.pp:
--------------------------------------------------------------------------------
1 | # @summary Set up the apt repo on Debian-based distros
2 | # @api private
3 | class jenkins::repo::debian (
4 | String $gpg_key_id = '63667EE74BBA1F0A08A698725BA31D57EF5975CA',
5 | ) {
6 | assert_private()
7 |
8 | include apt
9 |
10 | if $jenkins::lts {
11 | $location = "${jenkins::repo::base_url}/debian-stable"
12 | } else {
13 | $location = "${jenkins::repo::base_url}/debian"
14 | }
15 |
16 | apt::source { 'jenkins':
17 | location => $location,
18 | release => 'binary/',
19 | include => {
20 | 'src' => false,
21 | },
22 | key => {
23 | 'id' => $gpg_key_id,
24 | 'source' => "${location}/${jenkins::repo::gpg_key_filename}",
25 | },
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/manifests/repo/el.pp:
--------------------------------------------------------------------------------
1 | # @summary Set up the yum repo on Red Hat-based distros
2 | # @api private
3 | class jenkins::repo::el {
4 | assert_private()
5 |
6 | if $jenkins::lts {
7 | $baseurl = "${jenkins::repo::base_url}/redhat-stable/"
8 | } else {
9 | $baseurl = "${jenkins::repo::base_url}/redhat/"
10 | }
11 |
12 | yumrepo { 'jenkins':
13 | descr => 'Jenkins',
14 | baseurl => $baseurl,
15 | gpgcheck => 1,
16 | gpgkey => "${baseurl}${jenkins::repo::gpg_key_filename}",
17 | enabled => $jenkins::repo::enabled,
18 | proxy => $jenkins::repo_proxy,
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/manifests/repo/suse.pp:
--------------------------------------------------------------------------------
1 | # @summary Set up the Zypper repo on SUSE-based distros
2 | # @api private
3 | class jenkins::repo::suse {
4 | assert_private()
5 |
6 | if $jenkins::lts {
7 | $baseurl = "${jenkins::repo::base_url}/opensuse-stable/"
8 | } else {
9 | $baseurl = "${jenkins::repo::base_url}/opensuse/"
10 | }
11 |
12 | zypprepo { 'jenkins':
13 | descr => 'Jenkins',
14 | baseurl => $baseurl,
15 | gpgcheck => 1,
16 | gpgkey => "${baseurl}${jenkins::repo::gpg_key_filename}",
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/manifests/security.pp:
--------------------------------------------------------------------------------
1 | # Copyright 2014 RetailMeNot, Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # @summary Jenkins security configuration
16 | #
17 | class jenkins::security (
18 | String $security_model,
19 | ) {
20 | include jenkins::cli_helper
21 |
22 | Class['jenkins::cli_helper']
23 | -> Class['jenkins::security']
24 | -> Anchor['jenkins::end']
25 |
26 | # XXX not idempotent
27 | jenkins::cli::exec { "jenkins-security-${security_model}":
28 | command => [
29 | 'set_security',
30 | $security_model,
31 | ],
32 | unless => "\$HELPER_CMD get_authorization_strategyname | grep -q -e '^${security_model}\$'",
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/manifests/service.pp:
--------------------------------------------------------------------------------
1 | # @summary Manage the Jenkins service
2 | # @api private
3 | class jenkins::service {
4 | assert_private()
5 |
6 | service { 'jenkins':
7 | ensure => $jenkins::service_ensure,
8 | enable => $jenkins::service_enable,
9 | provider => $jenkins::service_provider,
10 | hasstatus => true,
11 | hasrestart => true,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/manifests/user.pp:
--------------------------------------------------------------------------------
1 | # Copyright 2014 RetailMeNot, Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # @summary Manage Jenkins user accounts
16 | #
17 | define jenkins::user (
18 | Pattern[/^[^@]+@[^@]+$/] $email,
19 | String $password,
20 | String $full_name = 'Managed by Puppet',
21 | String $public_key = '', # lint:ignore:params_empty_string_assignment
22 | Enum['present', 'absent'] $ensure = 'present',
23 | ) {
24 | include jenkins::cli_helper
25 |
26 | Class['jenkins::cli_helper']
27 | -> Jenkins::User[$title]
28 | -> Anchor['jenkins::end']
29 |
30 | case $ensure {
31 | 'present': {
32 | # XXX not idempotent
33 | jenkins::cli::exec { "create-jenkins-user-${title}":
34 | command => [
35 | 'create_or_update_user',
36 | $title,
37 | $email,
38 | "'${password}'",
39 | "'${full_name}'",
40 | "'${public_key}'",
41 | ],
42 | }
43 | }
44 | 'absent': {
45 | # XXX not idempotent
46 | jenkins::cli::exec { "delete-jenkins-user-${title}":
47 | command => [
48 | 'delete_user',
49 | $title,
50 | ],
51 | }
52 | }
53 | default: {
54 | fail "ensure must be 'present' or 'absent' but '${ensure}' was given"
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/manifests/user_setup.pp:
--------------------------------------------------------------------------------
1 | # @summary Optionally create the jenkins user and make sure all directories
2 | # have proper permissions setup.
3 | #
4 | # By having this in a separate class that is managed before
5 | # installing the package, we can effectivly override the
6 | # default local dir that is otherwise possibly created by
7 | # the package.
8 | #
9 | # @api private
10 | class jenkins::user_setup {
11 | assert_private()
12 |
13 | $dir_params = {
14 | ensure => directory,
15 | owner => $jenkins::user,
16 | group => $jenkins::group,
17 | mode => '0755',
18 | }
19 |
20 | # ensure_resource is used to try to maintain backwards compatiblity with
21 | # manifests that were able to external declare resources due to the
22 | # old conditional behavior of jenkins::plugin
23 | if $jenkins::manage_user {
24 | ensure_resource('user', $jenkins::user, {
25 | ensure => present,
26 | gid => $jenkins::group,
27 | home => $jenkins::localstatedir,
28 | managehome => false,
29 | system => true,
30 | })
31 | }
32 |
33 | if $jenkins::manage_group {
34 | ensure_resource('group', $jenkins::group, {
35 | ensure => present,
36 | system => true,
37 | })
38 | }
39 |
40 | $plugin_dir_params = $jenkins::purge_plugins ? {
41 | true => $dir_params + {
42 | 'purge' => true,
43 | 'recurse' => true,
44 | 'force' => true,
45 | 'notify' => Service['jenkins'],
46 | },
47 | default => $dir_params,
48 | }
49 |
50 | if $jenkins::manage_datadirs {
51 | ensure_resource('file', $jenkins::localstatedir, $dir_params)
52 | ensure_resource('file', $jenkins::plugin_dir, $plugin_dir_params)
53 | ensure_resource('file', $jenkins::job_dir, $dir_params)
54 | }
55 |
56 | # On Debian the service is started by default so it must be configured prior
57 | # to installation which is why it's configured in this file rather than config.pp
58 | $config_hash = $jenkins::params::config_hash_defaults + $jenkins::config_hash
59 |
60 | systemd::dropin_file { 'puppet-overrides.conf':
61 | unit => 'jenkins.service',
62 | content => epp("${module_name}/jenkins-override.epp", { 'environment' => $config_hash, 'dropin_config' => $jenkins::service_override }),
63 | notify_service => true,
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/manifests/users.pp:
--------------------------------------------------------------------------------
1 | # @summary Create Jenkins users
2 | # @api private
3 | class jenkins::users {
4 | assert_private()
5 |
6 | create_resources('jenkins::user', $jenkins::user_hash)
7 | }
8 |
--------------------------------------------------------------------------------
/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "puppet-jenkins",
3 | "version": "6.0.0",
4 | "author": "Vox Pupuli",
5 | "license": "Apache-2.0",
6 | "summary": "Manage the Jenkins continuous integration service with Puppet",
7 | "source": "https://github.com/voxpupuli/puppet-jenkins",
8 | "project_page": "https://github.com/voxpupuli/puppet-jenkins",
9 | "issues_url": "https://github.com/voxpupuli/puppet-jenkins/issues",
10 | "tags": [
11 | "jenkins",
12 | "jenkinsci",
13 | "voxpupuli"
14 | ],
15 | "operatingsystem_support": [
16 | {
17 | "operatingsystem": "RedHat",
18 | "operatingsystemrelease": [
19 | "8",
20 | "9"
21 | ]
22 | },
23 | {
24 | "operatingsystem": "CentOS",
25 | "operatingsystemrelease": [
26 | "9"
27 | ]
28 | },
29 | {
30 | "operatingsystem": "OracleLinux",
31 | "operatingsystemrelease": [
32 | "8",
33 | "9"
34 | ]
35 | },
36 | {
37 | "operatingsystem": "Rocky",
38 | "operatingsystemrelease": [
39 | "8",
40 | "9"
41 | ]
42 | },
43 | {
44 | "operatingsystem": "AlmaLinux",
45 | "operatingsystemrelease": [
46 | "8",
47 | "9"
48 | ]
49 | },
50 | {
51 | "operatingsystem": "SLES",
52 | "operatingsystemrelease": [
53 | "11",
54 | "12",
55 | "15"
56 | ]
57 | },
58 | {
59 | "operatingsystem": "OpenSuSE",
60 | "operatingsystemrelease": [
61 | "42",
62 | "15"
63 | ]
64 | },
65 | {
66 | "operatingsystem": "Ubuntu",
67 | "operatingsystemrelease": [
68 | "22.04",
69 | "24.04"
70 | ]
71 | },
72 | {
73 | "operatingsystem": "Debian",
74 | "operatingsystemrelease": [
75 | "12"
76 | ]
77 | }
78 | ],
79 | "dependencies": [
80 | {
81 | "name": "puppetlabs/stdlib",
82 | "version_requirement": ">= 4.19.0 < 10.0.0"
83 | },
84 | {
85 | "name": "puppetlabs/apt",
86 | "version_requirement": ">= 9.2.0 < 11.0.0"
87 | },
88 | {
89 | "name": "puppetlabs/java",
90 | "version_requirement": ">= 1.0.1 < 12.0.0"
91 | },
92 | {
93 | "name": "puppet/zypprepo",
94 | "version_requirement": ">= 2.0.0 < 6.0.0"
95 | },
96 | {
97 | "name": "puppet/archive",
98 | "version_requirement": ">= 1.3.0 < 8.0.0"
99 | },
100 | {
101 | "name": "puppet/systemd",
102 | "version_requirement": ">= 3.1.0 < 9.0.0"
103 | }
104 | ],
105 | "requirements": [
106 | {
107 | "name": "puppet",
108 | "version_requirement": ">= 7.0.0 < 9.0.0"
109 | }
110 | ]
111 | }
112 |
--------------------------------------------------------------------------------
/spec/acceptance/class_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper_acceptance'
4 |
5 | describe 'jenkins class' do
6 | context 'default parameters' do
7 | include_examples 'an idempotent resource' do
8 | let(:manifest) do
9 | <<~PUPPET
10 | class {'jenkins':
11 | cli => true,
12 | }
13 | PUPPET
14 | end
15 | end
16 |
17 | describe port(8080) do
18 | it {
19 | sleep(10) # Jenkins takes a while to start up
20 | is_expected.to be_listening
21 | }
22 | end
23 |
24 | describe file('/usr/share/java/jenkins-cli.jar') do
25 | it { is_expected.to be_file }
26 | it { is_expected.to be_readable.by('owner') }
27 | it { is_expected.to be_writable.by('owner') }
28 | it { is_expected.to be_readable.by('group') }
29 | it { is_expected.to be_readable.by('others') }
30 | end
31 |
32 | describe file('/etc/systemd/system/jenkins.service.d/puppet-overrides.conf') do
33 | it { is_expected.to be_file }
34 | it { is_expected.to contain 'Environment=' }
35 | end
36 |
37 | describe service('jenkins') do
38 | it { is_expected.to be_running }
39 | it { is_expected.to be_enabled }
40 | end
41 |
42 | describe process('java') do
43 | it { is_expected.to be_running }
44 | its(:args) { is_expected.to match(%r{-Djenkins\.install\.runSetupWizard=false}) }
45 | end
46 | end
47 |
48 | context 'executors' do
49 | include_examples 'an idempotent resource' do
50 | let(:manifest) do
51 | <<~PUPPET
52 | class {'jenkins':
53 | executors => 42,
54 | }
55 | PUPPET
56 | end
57 | end
58 |
59 | describe port(8080) do
60 | # jenkins should already have been running so we shouldn't have to
61 | # sleep
62 | it { is_expected.to be_listening }
63 | end
64 |
65 | describe service('jenkins') do
66 | it { is_expected.to be_running }
67 | it { is_expected.to be_enabled }
68 | end
69 |
70 | describe file('/var/lib/jenkins/config.xml') do
71 | it { is_expected.to contain ' 42' }
72 | end
73 | end
74 |
75 | context 'slaveagentport' do
76 | include_examples 'an idempotent resource' do
77 | let(:manifest) do
78 | <<~PUPPET
79 | class {'jenkins':
80 | slaveagentport => 7777,
81 | }
82 | PUPPET
83 | end
84 | end
85 |
86 | describe port(8080) do
87 | # jenkins should already have been running so we shouldn't have to
88 | # sleep
89 | it { is_expected.to be_listening }
90 | end
91 |
92 | describe service('jenkins') do
93 | it { is_expected.to be_running }
94 | it { is_expected.to be_enabled }
95 | end
96 |
97 | describe file('/var/lib/jenkins/config.xml') do
98 | it { is_expected.to contain ' 7777' }
99 | end
100 | end
101 | end
102 |
--------------------------------------------------------------------------------
/spec/acceptance/hieradata/common.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | jenkins::service_override:
3 | StartLimitIntervalSec: '0'
4 | StartLimitBurst: '0'
5 |
--------------------------------------------------------------------------------
/spec/acceptance/hieradata/family/Debian.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # Jenkins 2.479.1 requires Java 17 or newer
3 | java::package: openjdk-17-jdk
4 |
--------------------------------------------------------------------------------
/spec/acceptance/hieradata/family/RedHat.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # Jenkins 2.479.1 requires Java 17 or newer
3 | java::package: java-17-openjdk-devel
4 |
--------------------------------------------------------------------------------
/spec/acceptance/job_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper_acceptance'
4 |
5 | describe 'jenkins::job' do
6 | let(:test_build_job) do
7 | example = <<~EOS
8 |
9 |
10 |
11 | test job
12 | false
13 |
14 |
15 | true
16 | false
17 | false
18 | false
19 |
20 | false
21 |
22 |
23 | /usr/bin/true
24 |
25 |
26 |
27 |
28 |
29 | EOS
30 | # escape single quotes for puppet
31 | example.gsub("'", %q(\\\'))
32 | end
33 |
34 | context 'create' do
35 | it 'works with no errors' do
36 | pp = <<-EOS
37 | include jenkins
38 |
39 | # the historical assumption is that this will work without cli => true
40 | # set on the jenkins class
41 | jenkins::job { 'test-build-job':
42 | config => '#{test_build_job}',
43 | }
44 | EOS
45 |
46 | # Run it twice and test for idempotency
47 | apply(pp, catch_failures: true)
48 | # XXX idempotency is broken with at least jenkins 1.613
49 | # apply(pp, :catch_changes => true)
50 | end
51 |
52 | describe file('/var/lib/jenkins/jobs/test-build-job/config.xml') do
53 | it { is_expected.to be_file }
54 | it { is_expected.to be_owned_by 'jenkins' }
55 | it { is_expected.to be_grouped_into 'jenkins' }
56 | it { is_expected.to be_mode 644 }
57 | it { is_expected.to contain 'test job' }
58 | it { is_expected.to contain 'false' }
59 | it { is_expected.to contain '/usr/bin/true' }
60 | end
61 | end
62 |
63 | context 'no replace' do
64 | it 'does not replace an existing job' do
65 | pp_create = <<-EOS
66 | include jenkins
67 | jenkins::job {'test-noreplace-job':
68 | config => '#{test_build_job.gsub('test job', 'do not overwrite me')}',
69 | }
70 | EOS
71 |
72 | pp_update = <<-EOS
73 | include jenkins
74 | jenkins::job {'test-noreplace-job':
75 | config => '#{test_build_job}',
76 | replace => false,
77 | }
78 | EOS
79 |
80 | apply(pp_create, catch_failures: true)
81 | apply(pp_update, catch_failures: true)
82 | end
83 |
84 | describe file('/var/lib/jenkins/jobs/test-noreplace-job/config.xml') do
85 | it { is_expected.to be_file }
86 | it { is_expected.to be_owned_by 'jenkins' }
87 | it { is_expected.to be_grouped_into 'jenkins' }
88 | it { is_expected.to be_mode 644 }
89 | it { is_expected.to contain 'do not overwrite me' }
90 | end
91 | end
92 |
93 | context 'delete' do
94 | it 'works with no errors' do
95 | # create a test job so it can be deleted; job creation is not what
96 | # we're intending to be testing here
97 | pp = <<-EOS
98 | include jenkins
99 | jenkins::job { 'test-build-job':
100 | config => '#{test_build_job}',
101 | }
102 | EOS
103 |
104 | apply(pp)
105 |
106 | # test job deletion
107 | pp = <<-EOS
108 | include jenkins
109 | jenkins::job { 'test-build-job':
110 | ensure => 'absent',
111 | config => '#{test_build_job}',
112 | }
113 | EOS
114 |
115 | # Run it twice and test for idempotency
116 | apply(pp, catch_failures: true)
117 | # XXX idempotency is broken with at least jenkins 1.613
118 | # apply(pp, :catch_changes => true)
119 | end
120 |
121 | describe file('/var/lib/jenkins/jobs/test-build-job/config.xml') do
122 | # XXX Serverspec::Type::File doesn't support exists?
123 | it { is_expected.not_to be_file }
124 | end
125 | end
126 | end
127 |
--------------------------------------------------------------------------------
/spec/acceptance/plugin_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper_acceptance'
4 |
5 | describe 'jenkins class', order: :defined do
6 | PDIR = '/var/lib/jenkins/plugins'
7 |
8 | # files/directories to test plugin purging removal of unmanaged files
9 | FILES = [
10 | "#{PDIR}/a.hpi",
11 | "#{PDIR}/b.jpi",
12 | "#{PDIR}/c.txt",
13 | "#{PDIR}/a/foo",
14 | "#{PDIR}/b/bar",
15 | "#{PDIR}/c/baz"
16 | ].freeze
17 | DIRS = [
18 | "#{PDIR}/a",
19 | "#{PDIR}/b",
20 | "#{PDIR}/c"
21 | ].freeze
22 |
23 | shared_examples 'has_plugin' do |plugin|
24 | describe file("#{PDIR}/#{plugin}.hpi") do
25 | it { is_expected.to be_file }
26 | end
27 |
28 | describe file("#{PDIR}/#{plugin}") do
29 | it { is_expected.to be_directory }
30 | end
31 | end
32 |
33 | shared_context 'plugin_test_files' do
34 | before(:context) do
35 | shell("mkdir -p #{DIRS.join(' ')}")
36 | shell("touch #{FILES.join(' ')}")
37 | end
38 |
39 | after(:context) do
40 | shell("rm -rf #{DIRS.join(' ')} #{FILES.join(' ')}")
41 | end
42 | end
43 |
44 | context 'default parameters' do
45 | include_examples 'an idempotent resource' do
46 | let(:manifest) do
47 | <<~PUPPET
48 | include jenkins
49 | jenkins::plugin {'git-plugin':
50 | name => 'git',
51 | version => '2.3.4',
52 | }
53 | PUPPET
54 | end
55 | end
56 |
57 | it_behaves_like 'has_plugin', 'git'
58 | end
59 |
60 | describe 'plugin downgrade' do
61 | describe 'jquery3-api plugin' do
62 | describe 'installs version 3.6.0-r3' do
63 | include_examples 'an idempotent resource' do
64 | let(:manifest) do
65 | <<~PUPPET
66 | class {'jenkins':
67 | purge_plugins => true,
68 | }
69 |
70 | # actual plugin
71 | jenkins::plugin { 'jquery3-api':
72 | version => '3.6.0-4',
73 | }
74 | PUPPET
75 | end
76 | end
77 | end
78 |
79 | describe 'downgrades to 3.6.0-3' do
80 | include_examples 'an idempotent resource' do
81 | let(:manifest) do
82 | <<~PUPPET
83 | package{'unzip':
84 | ensure => present
85 | }
86 | class {'jenkins':
87 | purge_plugins => true,
88 | }
89 |
90 | # actual plugin
91 | jenkins::plugin { 'jquery3-api':
92 | version => '3.6.0-3',
93 | }
94 | PUPPET
95 | end
96 | end
97 | end
98 |
99 | describe command("unzip -p #{PDIR}/jquery3-api.hpi META-INF/MANIFEST.MF | sed 's/Plugin-Version: \\(.*\\)/\\1/;tx;d;:x'") do
100 | its(:stdout) { is_expected.to eq("3.6.0-3\n") }
101 | end
102 |
103 | it_behaves_like 'has_plugin', 'jquery3-api'
104 | end
105 | end
106 |
107 | describe 'plugin purging' do
108 | context 'true' do
109 | include_context 'plugin_test_files'
110 |
111 | it 'works with no errors' do
112 | pp = <<-EOS
113 | class {'jenkins':
114 | purge_plugins => true,
115 | }
116 |
117 | # Actual plugin
118 | jenkins::plugin { 'jquery3-api':
119 | version => '3.6.0-4',
120 | }
121 | EOS
122 |
123 | apply(pp, catch_failures: true)
124 | apply(pp, catch_changes: true)
125 | end
126 |
127 | it_behaves_like 'has_plugin', 'jquery3-api'
128 |
129 | (DIRS + FILES).each do |f|
130 | describe file(f) do
131 | it { is_expected.not_to exist }
132 | end
133 | end
134 | end
135 |
136 | context 'false' do
137 | include_context 'plugin_test_files'
138 |
139 | it 'works with no errors' do
140 | pp = <<-EOS
141 | class {'jenkins':
142 | purge_plugins => false,
143 | }
144 |
145 | # Actual plugin
146 | jenkins::plugin { 'jquery3-api':
147 | version => '3.6.0-4',
148 | }
149 | EOS
150 |
151 | apply(pp, catch_failures: true)
152 | apply(pp, catch_changes: true)
153 | end
154 |
155 | it_behaves_like 'has_plugin', 'jquery3-api'
156 |
157 | DIRS.each do |f|
158 | describe file(f) do
159 | it { is_expected.to be_directory }
160 | end
161 | end
162 |
163 | FILES.each do |f|
164 | describe file(f) do
165 | it { is_expected.to be_file }
166 | end
167 | end
168 | end
169 | end
170 | end
171 |
--------------------------------------------------------------------------------
/spec/classes/cli/config_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::cli::config' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | shared_examples 'validate_absolute_path' do |param|
11 | context 'absolute path' do
12 | let(:params) { { param => '/dne' } }
13 |
14 | it { is_expected.to compile }
15 | end
16 | end
17 |
18 | shared_examples 'validate_integer' do |param|
19 | context 'integer' do
20 | let(:params) { { param => 42 } }
21 |
22 | it { is_expected.to compile }
23 | end
24 | end
25 |
26 | shared_examples 'validate_numeric' do |param|
27 | context 'integer' do
28 | let(:params) { { param => 42 } }
29 |
30 | it { is_expected.to compile }
31 | end
32 |
33 | context 'float' do
34 | let(:params) { { param => 42.12345 } }
35 |
36 | it { is_expected.to compile }
37 | end
38 | end
39 |
40 | shared_examples 'validate_string' do |param|
41 | context 'string' do
42 | let(:params) { { param => 'foo' } }
43 |
44 | it { is_expected.to compile }
45 | end
46 | end
47 |
48 | describe 'parameters' do
49 | context 'accept all params undef' do
50 | it { is_expected.to compile }
51 | end
52 |
53 | describe 'cli_jar' do
54 | it_behaves_like 'validate_absolute_path', :cli_jar
55 | end
56 |
57 | # context 'port' do
58 | # it_behaves_like 'validate_integer', :port
59 | # end
60 | context 'url' do
61 | it_behaves_like 'validate_string', :url
62 | end
63 |
64 | context 'ssh_private_key' do
65 | it_behaves_like 'validate_absolute_path', :ssh_private_key
66 | end
67 |
68 | context 'puppet_helper' do
69 | it_behaves_like 'validate_absolute_path', :puppet_helper
70 | end
71 |
72 | context 'cli_tries' do
73 | it_behaves_like 'validate_integer', :cli_tries
74 | end
75 |
76 | context 'cli_try_sleep' do
77 | it_behaves_like 'validate_numeric', :cli_try_sleep
78 | end
79 |
80 | context 'ssh_private_key_content' do
81 | it_behaves_like 'validate_string', :ssh_private_key_content
82 |
83 | context 'when ssh_private_key is also set' do
84 | let(:params) do
85 | {
86 | ssh_private_key: '/dne',
87 | ssh_private_key_content: 'foo'
88 | }
89 | end
90 |
91 | context 'as non-root user' do
92 | let :facts do
93 | super().merge(id: 'user')
94 | end
95 |
96 | it do
97 | is_expected.to contain_file('/dne').with(
98 | ensure: 'file',
99 | mode: '0400',
100 | backup: false,
101 | owner: nil,
102 | group: nil
103 | )
104 | end
105 |
106 | it { is_expected.to contain_file('/dne').with_content('foo') }
107 | end
108 |
109 | context 'as root' do
110 | let :facts do
111 | super().merge(id: 'root')
112 | end
113 |
114 | it do
115 | is_expected.to contain_file('/dne').with(
116 | ensure: 'file',
117 | mode: '0400',
118 | backup: false,
119 | owner: 'jenkins',
120 | group: 'jenkins'
121 | )
122 | end
123 |
124 | it { is_expected.to contain_file('/dne').with_content('foo') }
125 | end
126 | end
127 | end
128 | end
129 | end
130 | end
131 | end
132 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_cli_helper_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::cli_helper' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | describe 'relationships' do
11 | it do
12 | is_expected.to contain_class('jenkins::cli')
13 | is_expected.to contain_class('jenkins::cli_helper').
14 | that_requires('Class[jenkins::cli]')
15 | end
16 |
17 | it do
18 | is_expected.to contain_class('jenkins::cli_helper').
19 | that_comes_before('Anchor[jenkins::end]')
20 | end
21 | end
22 |
23 | it do
24 | is_expected.to contain_file('/usr/share/java/puppet_helper.groovy').with(
25 | source: 'puppet:///modules/jenkins/puppet_helper.groovy',
26 | owner: 'jenkins',
27 | group: 'jenkins',
28 | mode: '0444'
29 | )
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'cli' do
11 | context 'default' do
12 | it { is_expected.to contain_class('jenkins').with(cli: true) }
13 | it { is_expected.to contain_class('jenkins::cli') }
14 | it { is_expected.to contain_class('jenkins::cli_helper') }
15 | end
16 |
17 | context '$cli => true' do
18 | let(:params) do
19 | { cli: true,
20 | cli_ssh_keyfile: '/path/to/key',
21 | cli_username: 'myuser',
22 | libdir: '/path/to/libdir',
23 | config_hash: { 'JENKINS_PORT' => { 'value' => '9000' } } }
24 | end
25 |
26 | it { is_expected.to contain_class('jenkins::cli') }
27 | it { is_expected.to contain_exec('jenkins-cli') }
28 | it { is_expected.to contain_exec('reload-jenkins').with_command(%r{http://localhost:9000}) }
29 | it { is_expected.to contain_exec('reload-jenkins').with_command(%r{-i\s'/path/to/key'}) }
30 | it { is_expected.to contain_exec('reload-jenkins').that_requires('File[/path/to/libdir/jenkins-cli.jar]') }
31 | it { is_expected.to contain_exec('safe-restart-jenkins') }
32 |
33 | describe 'jenkins::cli' do
34 | describe 'relationships' do
35 | it do
36 | is_expected.to contain_class('jenkins::cli').
37 | that_requires('Class[jenkins::service]')
38 | end
39 |
40 | it do
41 | is_expected.to contain_class('jenkins::cli').
42 | that_comes_before('Anchor[jenkins::end]')
43 | end
44 | end
45 | end
46 | end
47 |
48 | context '$cli => false' do
49 | let(:params) { { cli: false } }
50 |
51 | it { is_expected.not_to contain_class('jenkins::cli') }
52 | it { is_expected.not_to contain_class('jenkins::cli_helper') }
53 | end
54 | end
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_config_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'config' do
11 | context 'default' do
12 | it { is_expected.to contain_class('jenkins::config') }
13 | it { is_expected.to contain_jenkins__plugin('credentials') }
14 |
15 | it do
16 | is_expected.to contain_file('/etc/systemd/system/jenkins.service.d/puppet-overrides.conf').
17 | with_content <<~CONFIG
18 | [Service]
19 | Environment="JAVA_OPTS=-Djava.awt.headless=true -Djenkins.install.runSetupWizard=false"
20 | CONFIG
21 | end
22 | end
23 |
24 | context 'create config' do
25 | let(:params) { { config_hash: { 'AJP_PORT' => { 'value' => '1234' } }, service_override: { 'WorkingDirectory' => '/example/path' } } }
26 |
27 | it do
28 | is_expected.to contain_file('/etc/systemd/system/jenkins.service.d/puppet-overrides.conf').
29 | with_content <<~CONFIG
30 | [Service]
31 | Environment="JAVA_OPTS=-Djava.awt.headless=true -Djenkins.install.runSetupWizard=false"
32 | Environment="AJP_PORT=1234"
33 | WorkingDirectory=/example/path
34 | CONFIG
35 | end
36 | end
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_direct_download_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 | let(:params) { { direct_download: 'http://local.space/jenkins.rpm' } }
10 |
11 | describe 'direct_download' do
12 | context 'default' do
13 | it { is_expected.to contain_package('jenkins').with_installed }
14 | it { is_expected.not_to contain_class('jenkins::package') }
15 | it { is_expected.to contain_class('jenkins::direct_download') }
16 | end
17 |
18 | context 'with version' do
19 | let(:params) { { version: '1.2.3' } }
20 |
21 | it { is_expected.to contain_package('jenkins').with_ensure('1.2.3') }
22 | end
23 |
24 | context 'package dir created' do
25 | it { is_expected.to contain_file('/var/cache/jenkins_pkgs').with_ensure('directory') }
26 | end
27 |
28 | context 'staging resource created' do
29 | it do
30 | is_expected.to contain_archive('jenkins.rpm').with(
31 | source: 'http://local.space/jenkins.rpm',
32 | path: '/var/cache/jenkins_pkgs/jenkins.rpm',
33 | cleanup: false,
34 | extract: false
35 | ).that_comes_before('Package[jenkins]')
36 | end
37 | end
38 |
39 | context 'package removable' do
40 | let(:params) { { version: 'absent', direct_download: 'http://local.space/jenkins.rpm' } }
41 |
42 | it { is_expected.not_to contain_staging__file('jenkins.rpm') }
43 | it { is_expected.to contain_package('jenkins').with_ensure('absent') }
44 | end
45 |
46 | context 'unsupported provider fails' do
47 | let(:params) { { package_provider: false, direct_download: 'http://local.space/jenkins.rpm' } }
48 |
49 | it { is_expected.to compile.and_raise_error(%r{got Boolean}) }
50 | end
51 | end
52 | end
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_firewall_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 | let(:pre_condition) { ['define firewall($action, $state, $dport, $proto) {}'] }
10 | let(:params) { { configure_firewall: true } }
11 |
12 | context 'firewall' do
13 | it { is_expected.to contain_firewall('500 allow Jenkins inbound traffic') }
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_jobs_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'jobs' do
11 | context 'default' do
12 | it { is_expected.to contain_class('jenkins::jobs') }
13 | end
14 |
15 | context 'with one job' do
16 | let(:params) { { job_hash: { 'build' => { 'config' => '' } } } }
17 |
18 | it { is_expected.to contain_jenkins__job('build').with_config('') }
19 | end
20 |
21 | context 'with cli disabled' do
22 | let(:params) do
23 | {
24 | service_ensure: 'stopped',
25 | cli: false,
26 | job_hash: { 'build' => { 'config' => '' } }
27 | }
28 | end
29 |
30 | it { is_expected.to compile.and_raise_error(%r{Management of Jenkins jobs requires \\\$jenkins::service_ensure to be set to 'running'}) }
31 | end
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_master_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::master' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 | let(:params) { { version: '1.2.3' } }
10 | let(:pre_condition) { 'include jenkins' }
11 |
12 | it { is_expected.to contain_jenkins__plugin('swarm').with_version('1.2.3') }
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_package_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | describe 'package' do
11 | context 'default' do
12 | it { is_expected.to contain_package('jenkins').with_installed }
13 | end
14 |
15 | context 'with version' do
16 | let(:params) { { version: '1.2.3' } }
17 |
18 | it { is_expected.to contain_package('jenkins').with_ensure('1.2.3') }
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_plugins_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'plugins' do
11 | context 'default' do
12 | it { is_expected.to contain_class('jenkins::plugins') }
13 | end
14 |
15 | context 'install plugin' do
16 | let(:params) { { plugin_hash: { 'git' => { 'version' => '1.1.1' } } } }
17 |
18 | it { is_expected.to contain_jenkins__plugin('git').with_version('1.1.1') }
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_proxy_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'proxy' do
11 | context 'default' do
12 | it { is_expected.to contain_class('jenkins::proxy') }
13 | end
14 |
15 | context 'with basic proxy config' do
16 | let(:params) { { proxy_host: 'myhost', proxy_port: 1234 } }
17 |
18 | it { is_expected.to create_class('jenkins::proxy') }
19 |
20 | it do
21 | is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(
22 | owner: 'jenkins',
23 | group: 'jenkins',
24 | mode: '0644'
25 | )
26 | end
27 |
28 | it { is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(content: %r{myhost}) }
29 | it { is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(content: %r{1234}) }
30 | it { is_expected.to contain_file('/var/lib/jenkins/proxy.xml').without(content: %r{}) }
31 | end
32 |
33 | context 'with "no_proxy_list" proxy config' do
34 | let(:params) { { proxy_host: 'myhost', proxy_port: 1234, no_proxy_list: ['example.com', 'test.host.net'] } }
35 |
36 | it { is_expected.to create_class('jenkins::proxy') }
37 |
38 | it do
39 | is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(
40 | owner: 'jenkins',
41 | group: 'jenkins',
42 | mode: '0644'
43 | )
44 | end
45 |
46 | it { is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(content: %r{myhost}) }
47 | it { is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(content: %r{1234}) }
48 | it { is_expected.to contain_file('/var/lib/jenkins/proxy.xml').with(content: %r{example\.com\ntest\.host\.net}) }
49 | end
50 | end
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_repo_debian_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}", if: os_facts[:osfamily] == 'Debian' do
8 | let(:facts) { os_facts }
9 |
10 | context 'repo::debian' do
11 | shared_examples 'an apt catalog' do
12 | it { is_expected.to contain_class('apt') }
13 | it { is_expected.to contain_apt__source('jenkins') }
14 | end
15 |
16 | describe 'default' do
17 | it_behaves_like 'an apt catalog'
18 | it { is_expected.to contain_apt__source('jenkins').with_location('https://pkg.jenkins.io/debian-stable') }
19 | end
20 |
21 | describe 'lts = true' do
22 | let(:params) { { lts: true } }
23 |
24 | it_behaves_like 'an apt catalog'
25 | it { is_expected.to contain_apt__source('jenkins').with_location('https://pkg.jenkins.io/debian-stable') }
26 | end
27 |
28 | describe 'lts = false' do
29 | let(:params) { { lts: false } }
30 |
31 | it_behaves_like 'an apt catalog'
32 | it { is_expected.to contain_apt__source('jenkins').with_location('https://pkg.jenkins.io/debian') }
33 | end
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_repo_el_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os(supported_os: [{ 'operatingsystem' => 'CentOS' }]).each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'repo::el' do
11 | describe 'default' do
12 | it { is_expected.to contain_yumrepo('jenkins').with_baseurl('https://pkg.jenkins.io/redhat-stable/') }
13 | it { is_expected.to contain_yumrepo('jenkins').with_proxy(nil) }
14 | end
15 |
16 | describe 'lts = true' do
17 | let(:params) { { lts: true } }
18 |
19 | it { is_expected.to contain_yumrepo('jenkins').with_baseurl('https://pkg.jenkins.io/redhat-stable/') }
20 | it { is_expected.to contain_yumrepo('jenkins').with_proxy(nil) }
21 | end
22 |
23 | describe 'lts = false' do
24 | let(:params) { { lts: false } }
25 |
26 | it { is_expected.to contain_yumrepo('jenkins').with_proxy(nil) }
27 | it { is_expected.to contain_yumrepo('jenkins').with_baseurl('https://pkg.jenkins.io/redhat/') }
28 | end
29 |
30 | describe 'repo_proxy is set' do
31 | let(:params) { { repo_proxy: 'http://proxy:8080/' } }
32 |
33 | it { is_expected.to contain_yumrepo('jenkins').with_proxy('http://proxy:8080/') }
34 | end
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_repo_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | describe 'repo' do
11 | describe 'default' do
12 | case os_facts[:os]['family']
13 | when 'RedHat'
14 | describe 'RedHat' do
15 | it { is_expected.to compile.with_all_deps }
16 | it { is_expected.to contain_class('jenkins::repo::el') }
17 | it { is_expected.not_to contain_class('jenkins::repo::suse') }
18 | it { is_expected.not_to contain_class('jenkins::repo::debian') }
19 | it { is_expected.to contain_package('jenkins').that_requires('Yumrepo[jenkins]') }
20 | end
21 |
22 | describe 'repo => false' do
23 | let(:params) { { repo: false } }
24 |
25 | it { is_expected.to compile.with_all_deps }
26 | it { is_expected.not_to contain_class('jenkins::repo') }
27 | it { is_expected.not_to contain_class('jenkins::repo::el') }
28 | it { is_expected.not_to contain_class('jenkins::repo::suse') }
29 | it { is_expected.not_to contain_class('jenkins::repo::debian') }
30 | end
31 | when 'Suse'
32 | describe 'Suse' do
33 | it { is_expected.to compile.with_all_deps }
34 | it { is_expected.to contain_class('jenkins::repo::suse') }
35 | it { is_expected.not_to contain_class('jenkins::repo::el') }
36 | it { is_expected.not_to contain_class('jenkins::repo::debian') }
37 | it { is_expected.to contain_package('jenkins').that_requires('Zypprepo[jenkins]') }
38 | end
39 | when 'Debian'
40 | describe 'Debian' do
41 | it { is_expected.to compile.with_all_deps }
42 | it { is_expected.to contain_class('jenkins::repo::debian') }
43 | it { is_expected.not_to contain_class('jenkins::repo::suse') }
44 | it { is_expected.not_to contain_class('jenkins::repo::el') }
45 | it { is_expected.to contain_package('jenkins').that_requires('Apt::Source[jenkins]') }
46 | end
47 | end
48 | end
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_repo_suse_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}", if: os_facts[:osfamily] == 'Suse' do
8 | let(:facts) { os_facts }
9 |
10 | context 'repo::suse' do
11 | describe 'default' do
12 | it { is_expected.to contain_zypprepo('jenkins').with_baseurl('https://pkg.jenkins.io/opensuse-stable/') }
13 | end
14 |
15 | describe 'lts = true' do
16 | let(:params) { { lts: true } }
17 |
18 | it { is_expected.to contain_zypprepo('jenkins').with_baseurl('https://pkg.jenkins.io/opensuse-stable/') }
19 | end
20 |
21 | describe 'lts = false' do
22 | let(:params) { { lts: false } }
23 |
24 | it { is_expected.to contain_zypprepo('jenkins').with_baseurl('https://pkg.jenkins.io/opensuse/') }
25 | end
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_security_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::security' do
6 | on_supported_os.each do |os, facts|
7 | context "on #{os}" do
8 | let(:facts) { facts }
9 | let(:params) { { security_model: 'test' } }
10 |
11 | describe 'relationships' do
12 | it do
13 | is_expected.to contain_class('jenkins::security').
14 | that_requires('Class[jenkins::cli_helper]')
15 | end
16 |
17 | it do
18 | is_expected.to contain_class('jenkins::security').
19 | that_comes_before('Anchor[jenkins::end]')
20 | end
21 |
22 | it { is_expected.to compile }
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_user_setup_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'user_setup' do
11 | context 'default' do
12 | it { is_expected.to contain_user('jenkins') }
13 | it { is_expected.to contain_group('jenkins') }
14 |
15 | [
16 | '/var/lib/jenkins',
17 | '/var/lib/jenkins/plugins',
18 | '/var/lib/jenkins/jobs'
19 | ].each do |datadir|
20 | it do
21 | is_expected.to contain_file(datadir).with(
22 | ensure: 'directory',
23 | mode: '0755',
24 | group: 'jenkins',
25 | owner: 'jenkins'
26 | )
27 | end
28 | end
29 | end
30 |
31 | context 'unmanaged' do
32 | let(:params) do
33 | {
34 | manage_user: false,
35 | manage_group: false,
36 | manage_datadirs: false
37 | }
38 | end
39 |
40 | it { is_expected.not_to contain_user('jenkins') }
41 | it { is_expected.not_to contain_group('jenkins') }
42 | it { is_expected.not_to contain_file('/var/lib/jenkins') }
43 | it { is_expected.not_to contain_file('/var/lib/jenkins/jobs') }
44 | it { is_expected.not_to contain_file('/var/lib/jenkins/plugins') }
45 | end
46 |
47 | context 'custom home' do
48 | let(:params) do
49 | {
50 | localstatedir: '/custom/jenkins'
51 | }
52 | end
53 |
54 | it { is_expected.to contain_user('jenkins').with_home('/custom/jenkins') }
55 | it { is_expected.to contain_file('/custom/jenkins') }
56 | it { is_expected.to contain_file('/custom/jenkins/plugins') }
57 | it { is_expected.to contain_file('/custom/jenkins/jobs') }
58 | end
59 | end
60 | end
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/spec/classes/jenkins_users_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'users' do
11 | context 'default' do
12 | it { is_expected.to contain_class('jenkins::users') }
13 | end
14 |
15 | context 'with testuser' do
16 | let(:params) do
17 | { user_hash: { 'user' => {
18 | 'email' => 'user@example.com',
19 | 'password' => 'test'
20 | } } }
21 | end
22 |
23 | it { is_expected.to contain_jenkins__user('user').with_email('user@example.com').with_password('test') }
24 | end
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/defines/jenkins_cli_exec_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::cli::exec' do
6 | let(:title) { 'foo' }
7 |
8 | on_supported_os.each do |os, os_facts|
9 | context "on #{os}" do
10 | let(:facts) { os_facts }
11 | let(:helper_cmd) { '/bin/cat /usr/share/java/puppet_helper.groovy | /usr/bin/java -jar /usr/share/java/jenkins-cli.jar -s http://127.0.0.1:8080 groovy =' }
12 |
13 | describe 'relationships' do
14 | it do
15 | is_expected.to contain_jenkins__cli__exec('foo').
16 | that_requires('Class[jenkins::cli_helper]')
17 | end
18 |
19 | it do
20 | is_expected.to contain_jenkins__cli__exec('foo').
21 | that_comes_before('Anchor[jenkins::end]')
22 | end
23 | end
24 |
25 | describe 'title =>' do
26 | context 'foo' do
27 | # default title...
28 |
29 | it do
30 | is_expected.to contain_exec('foo').with(
31 | command: "#{helper_cmd} foo",
32 | tries: 10,
33 | try_sleep: 10,
34 | unless: nil
35 | )
36 | end
37 |
38 | it { is_expected.to contain_exec('foo').that_notifies('Class[jenkins::cli::reload]') }
39 | end
40 |
41 | context 'bar' do
42 | let(:title) { 'bar' }
43 |
44 | it do
45 | is_expected.to contain_exec('bar').with(
46 | command: "#{helper_cmd} bar",
47 | tries: 10,
48 | try_sleep: 10,
49 | unless: nil
50 | )
51 | end
52 |
53 | it { is_expected.to contain_exec('bar').that_notifies('Class[jenkins::cli::reload]') }
54 | end
55 | end
56 |
57 | describe 'command =>' do
58 | context 'bar' do
59 | let(:params) { { command: 'bar' } }
60 |
61 | it do
62 | is_expected.to contain_exec('foo').with(
63 | command: "#{helper_cmd} bar",
64 | tries: 10,
65 | try_sleep: 10,
66 | unless: nil
67 | )
68 | end
69 | end
70 |
71 | context "['bar']" do
72 | let(:params) { { command: %w[bar] } }
73 |
74 | it do
75 | is_expected.to contain_exec('foo').with(
76 | command: "#{helper_cmd} bar",
77 | tries: 10,
78 | try_sleep: 10,
79 | unless: nil
80 | )
81 | end
82 | end
83 |
84 | context "['bar', 'baz']" do
85 | let(:params) { { command: %w[bar baz] } }
86 |
87 | it do
88 | is_expected.to contain_exec('foo').with(
89 | command: "#{helper_cmd} bar baz",
90 | tries: 10,
91 | try_sleep: 10,
92 | unless: nil
93 | )
94 | end
95 | end
96 | end
97 |
98 | describe 'unless =>' do
99 | context 'bar' do
100 | let(:params) { { unless: 'bar' } }
101 |
102 | it do
103 | is_expected.to contain_exec('foo').with(
104 | command: "#{helper_cmd} foo",
105 | environment: ["HELPER_CMD=eval #{helper_cmd}"],
106 | unless: 'bar',
107 | tries: 10,
108 | try_sleep: 10
109 | )
110 | end
111 | end
112 | end
113 | end
114 | end
115 | end
116 |
--------------------------------------------------------------------------------
/spec/defines/jenkins_credentials_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::credentials' do
6 | let(:title) { 'foo' }
7 | let(:helper_cmd) { '/usr/bin/java -jar cli.jar -s http://127.0.0.1:8080 groovy /var/lib/jenkins/puppet_helper.groovy' }
8 | let(:pre_condition) do
9 | "class jenkins::cli_helper { $helper_cmd = '#{helper_cmd}' }"
10 | end
11 |
12 | on_supported_os.each do |os, os_facts|
13 | context "on #{os}" do
14 | let(:facts) { os_facts }
15 |
16 | describe 'relationships' do
17 | let(:params) { { password: 'foo' } }
18 |
19 | it do
20 | is_expected.to contain_jenkins__credentials('foo').
21 | that_requires('Class[jenkins::cli_helper]')
22 | end
23 |
24 | it do
25 | is_expected.to contain_jenkins__credentials('foo').
26 | that_comes_before('Anchor[jenkins::end]')
27 | end
28 | end
29 |
30 | describe 'with ensure is present' do
31 | let(:params) do
32 | {
33 | ensure: 'present',
34 | password: 'mypass'
35 | }
36 | end
37 |
38 | it {
39 | is_expected.to contain_jenkins__cli__exec('create-jenkins-credentials-foo').with(command: ['create_or_update_credentials', title.to_s, "'mypass'",
40 | "''", "'Managed by Puppet'", "''"],
41 | unless: "for i in $(seq 1 10); do $HELPER_CMD credential_info #{title} && break || sleep 10; done | grep #{title}")
42 | }
43 | end
44 |
45 | describe 'with ensure is absent' do
46 | let(:params) do
47 | {
48 | ensure: 'absent',
49 | password: 'mypass'
50 | }
51 | end
52 |
53 | it { is_expected.to contain_jenkins__cli__exec('delete-jenkins-credentials-foo').with(command: ['delete_credentials', title.to_s]) }
54 | end
55 |
56 | describe 'with uuid set' do
57 | let(:params) do
58 | {
59 | ensure: 'present',
60 | password: 'mypass',
61 | uuid: 'e94d3b98-5ba4-43b9-89ed-79a08ea97f6f'
62 | }
63 | end
64 |
65 | it {
66 | is_expected.to contain_jenkins__cli__exec('create-jenkins-credentials-foo').with(command: ['create_or_update_credentials', title.to_s, "'mypass'",
67 | "'e94d3b98-5ba4-43b9-89ed-79a08ea97f6f'", "'Managed by Puppet'", "''"],
68 | unless: "for i in $(seq 1 10); do $HELPER_CMD credential_info #{title} && break || sleep 10; done | grep #{title}")
69 | }
70 | end
71 | end
72 | end
73 | end
74 |
--------------------------------------------------------------------------------
/spec/defines/jenkins_job_present_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::job::present' do
6 | let(:title) { 'myjob' }
7 | let(:pre_condition) do
8 | "class { 'jenkins': cli => true, }"
9 | end
10 |
11 | on_supported_os.each do |os, os_facts|
12 | context "on #{os}" do
13 | let(:facts) { os_facts }
14 |
15 | it { is_expected.to compile.and_raise_error(%r{Please set one of}) }
16 |
17 | describe 'with both_config_and_config_file_set' do
18 | quotes = ""
19 | let(:params) { { config: quotes, config_file: quotes } }
20 |
21 | it { is_expected.to compile.and_raise_error(%r{You cannot set both}) }
22 | end
23 |
24 | describe 'with config_file set' do
25 | let(:config_file) { File.expand_path(File.join(__dir__, '..', 'fixtures', 'testjob.xml')) }
26 | let(:params) { { config_file: config_file } }
27 |
28 | it { is_expected.to contain_exec('jenkins create-job myjob') }
29 | it { is_expected.to contain_exec('jenkins update-job myjob') }
30 | it { is_expected.not_to contain_exec('jenkins delete-job myjob') }
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/defines/jenkins_user_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins::user', type: :define do
6 | let(:title) { 'foo' }
7 |
8 | on_supported_os.each do |os, os_facts|
9 | context "on #{os}" do
10 | let(:facts) { os_facts }
11 |
12 | describe 'relationships' do
13 | let(:params) { { email: 'foo@example.org', password: 'foo' } }
14 |
15 | it do
16 | is_expected.to contain_jenkins__user('foo').
17 | that_requires('Class[jenkins::cli_helper]')
18 | end
19 |
20 | it do
21 | is_expected.to contain_jenkins__user('foo').
22 | that_comes_before('Anchor[jenkins::end]')
23 | end
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/fixtures/testjob.xml:
--------------------------------------------------------------------------------
1 | sourcedconfig
2 |
--------------------------------------------------------------------------------
/spec/functions/jenkins_port_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins_port' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'with default parameters' do
11 | let(:pre_condition) do
12 | 'include jenkins'
13 | end
14 |
15 | it 'defaults to 8080' do
16 | is_expected.to run.with_params.and_return(8080)
17 | end
18 | end
19 |
20 | context 'with overwritten configuration' do
21 | let(:pre_condition) do
22 | <<-ENDPUPPET
23 | class { 'jenkins':
24 | config_hash => {'JENKINS_PORT' => {'value' => '1337'}},
25 | }
26 | ENDPUPPET
27 | end
28 |
29 | it 'is our overwritten port' do
30 | is_expected.to run.with_params.and_return('1337')
31 | end
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/functions/jenkins_prefix_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins_prefix' do
6 | on_supported_os.each do |os, os_facts|
7 | context "on #{os}" do
8 | let(:facts) { os_facts }
9 |
10 | context 'with default parameters' do
11 | let(:pre_condition) do
12 | 'include jenkins'
13 | end
14 |
15 | it { is_expected.to run.with_params.and_return('') }
16 | end
17 |
18 | context 'with overwritten configuration' do
19 | let(:pre_condition) do
20 | <<-ENDPUPPET
21 | class { 'jenkins':
22 | config_hash => {'PREFIX' => {'value' => '/test'}},
23 | }
24 | ENDPUPPET
25 | end
26 |
27 | it { is_expected.to run.with_params.and_return('/test') }
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/spec/setup_acceptance_node.pp:
--------------------------------------------------------------------------------
1 | # Facter < 4 needs lsb-release for os.distro.codename
2 | if versioncmp($facts['facterversion'], '4.0.0') < 0 and $facts['os']['family'] == 'Debian' {
3 | package { 'lsb-release':
4 | ensure => 'installed',
5 | }
6 | }
7 |
8 | # jenkins::job::present needs diff
9 | if $facts['os']['family'] == 'RedHat' {
10 | package { 'diffutils':
11 | ensure => present,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/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 | Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f }
25 |
--------------------------------------------------------------------------------
/spec/spec_helper_acceptance.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'voxpupuli/acceptance/spec_helper_acceptance'
4 |
5 | configure_beaker
6 |
7 | def apply(pp, options = {})
8 | options[:debug] = true if ENV.key?('PUPPET_DEBUG')
9 |
10 | apply_manifest(pp, options)
11 | end
12 |
--------------------------------------------------------------------------------
/spec/unit/facter/plugins_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe 'jenkins_plugins', type: :fact do
6 | subject { Facter.value(:jenkins_plugins) }
7 |
8 | let(:plugins) { {} }
9 |
10 | before do
11 | Facter.clear
12 | Facter.loadfacts
13 | allow(Puppet::Jenkins::Plugins).to receive(:available).and_return(plugins)
14 |
15 | overridden_kernel = kernel
16 | Facter.add(:kernel, weight: 9999) do
17 | setcode { overridden_kernel }
18 | end
19 | end
20 |
21 | after { Facter.clear }
22 |
23 | context 'on Linux' do
24 | let(:kernel) { 'Linux' }
25 |
26 | after { expect(Puppet::Jenkins::Plugins).to have_received(:available) }
27 |
28 | context 'with no plugins' do
29 | it { is_expected.to be_instance_of String }
30 | it { is_expected.to be_empty }
31 | end
32 |
33 | context 'with one plugin' do
34 | let(:plugins) do
35 | {
36 | 'greenballs' => { plugin_version: '1.1', description: 'rspec' }
37 | }
38 | end
39 |
40 | it { is_expected.to be_instance_of String }
41 | it { is_expected.to eql 'greenballs 1.1' }
42 | end
43 |
44 | context 'with multiple plugins' do
45 | let(:plugins) do
46 | {
47 | 'greenballs' => { plugin_version: '1.1', description: 'rspec' },
48 | 'git' => { plugin_version: '1.7', description: 'rspec' }
49 | }
50 | end
51 |
52 | it { is_expected.to be_instance_of String }
53 | it { is_expected.to eql 'git 1.7, greenballs 1.1' }
54 | end
55 | end
56 |
57 | context 'on FreeBSD' do
58 | let(:kernel) { 'FreeBSD' }
59 |
60 | after { expect(Puppet::Jenkins::Plugins).not_to have_received(:available) }
61 |
62 | it { is_expected.to be_nil }
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/spec/unit/jenkins_plugins_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'puppet/jenkins/plugins'
5 |
6 | describe Puppet::Jenkins::Plugins do
7 | let(:git_plugin) do
8 | { 'buildDate' => 'Jan 08, 2014',
9 | 'dependencies' =>
10 | [{ 'name' => 'promoted-builds', 'optional' => true, 'version' => '2.7' },
11 | { 'name' => 'token-macro', 'optional' => true, 'version' => '1.5.1' },
12 | { 'name' => 'ssh-credentials', 'optional' => false, 'version' => '1.5.1' },
13 | { 'name' => 'scm-api', 'optional' => false, 'version' => '0.1' },
14 | { 'name' => 'credentials', 'optional' => false, 'version' => '1.9.3' },
15 | { 'name' => 'multiple-scms', 'optional' => true, 'version' => '0.2' },
16 | { 'name' => 'parameterized-trigger', 'optional' => true, 'version' => '2.4' },
17 | { 'name' => 'git-client', 'optional' => false, 'version' => '1.6.0' }],
18 | 'developers' =>
19 | [{ 'developerId' => 'kohsuke', 'name' => 'Kohsuke Kawaguchi' },
20 | { 'developerId' => 'ndeloof',
21 | 'email' => 'nicolas.deloof@gmail.com',
22 | 'name' => 'Nicolas De Loof' }],
23 | 'excerpt' =>
24 | "This plugin allows use of Git as a build SCM. A recent Git runtime is required (1.7.9 minimum, 1.8.x recommended). Plugin is only tested on official git client. Use exotic installations at your own risks.",
25 | 'gav' => 'org.jenkins-ci.plugins:git:2.0.1',
26 | 'labels' => ['scm'],
27 | 'name' => 'git',
28 | 'previousTimestamp' => '2013-10-22T22:00:16.00Z',
29 | 'previousVersion' => '2.0',
30 | 'releaseTimestamp' => '2014-01-08T21:46:20.00Z',
31 | 'requiredCore' => '1.480',
32 | 'scm' => 'github.com',
33 | 'sha1' => 'r5bK/IP8soP08D55Xpcx5yWHzdY=',
34 | 'title' => 'Git Plugin',
35 | 'url' => 'http://updates.jenkins-ci.org/download/plugins/git/2.0.1/git.hpi',
36 | 'version' => '2.0.1',
37 | 'wiki' => 'https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin' }
38 | end
39 |
40 | describe '.exists?' do
41 | subject(:exists) { described_class.exists? }
42 |
43 | context 'if jenkins does not exist' do
44 | before do
45 | allow(Puppet::Jenkins).to receive(:home_dir).and_return(nil)
46 | end
47 |
48 | it { is_expected.to be false }
49 | end
50 |
51 | context 'if jenkins exists' do
52 | let(:home) { '/var/lib/jenkins' }
53 | let(:dir_exists) { false }
54 |
55 | before do
56 | allow(Puppet::Jenkins).to receive(:home_dir).and_return(home)
57 | expect(File).to receive(:directory?).with(File.join(home, 'plugins')).and_return(dir_exists)
58 | end
59 |
60 | context 'and the directory exists' do
61 | let(:dir_exists) { true }
62 |
63 | it { is_expected.to be true }
64 | end
65 |
66 | context 'and the directory does not exist' do
67 | it { is_expected.to be false }
68 | end
69 | end
70 | end
71 |
72 | describe '.available' do
73 | subject(:available) { described_class.available }
74 |
75 | context 'when plugins do not exist' do
76 | before do
77 | expect(described_class).to receive(:exists?).and_return(false)
78 | end
79 |
80 | it { is_expected.to be_empty }
81 | it { is_expected.to be_instance_of Hash }
82 | end
83 |
84 | context 'when plugins exist' do
85 | it 'generates a list of plugins' do
86 | pending 'This is too hard to unit test, feh.'
87 | raise
88 | end
89 | end
90 | end
91 |
92 | describe 'manifest_data' do
93 | subject(:data) { described_class.manifest_data(data_str) }
94 |
95 | context 'with a plugin version that is hyphenated' do
96 | let(:data_str) do
97 | '
98 | Plugin-Version: 1.7.2-1
99 | Jenkins-Version: 1.456
100 | '
101 | end
102 |
103 | it 'has the properly hyphenated plugin version' do
104 | expect(data[:plugin_version]).to eql('1.7.2-1')
105 | end
106 | end
107 |
108 | context 'with "standard" looking manifest data' do
109 | let(:data_str) do
110 | '
111 | Manifest-Version: 1.0
112 | Archiver-Version: Plexus Archiver
113 | Created-By: Apache Maven
114 | Built-By: jglick
115 | Build-Jdk: 1.7.0_11
116 | Extension-Name: ant
117 | Implementation-Title: ant
118 | Implementation-Version: 1.2
119 | Group-Id: org.jenkins-ci.plugins
120 | Short-Name: ant
121 | Long-Name: Ant Plugin
122 | Url: http://wiki.jenkins-ci.org/display/JENKINS/Ant+Plugin
123 | Plugin-Version: 1.2
124 | Hudson-Version: 1.456
125 | Jenkins-Version: 1.456
126 | Plugin-Developers:
127 |
128 | '
129 | end
130 |
131 | it { is_expected.to be_instance_of Hash }
132 |
133 | it 'parses the right plugin version' do
134 | expect(data[:plugin_version]).to eql('1.2')
135 | end
136 | end
137 |
138 | context 'with a more complex manifest' do
139 | let(:data_str) do
140 | '
141 | Manifest-Version: 1.0
142 | Archiver-Version: Plexus Archiver
143 | Created-By: Apache Maven
144 | Built-By: nicolas
145 | Build-Jdk: 1.7.0_45
146 | Extension-Name: git
147 | Specification-Title: Integrates Jenkins with GIT SCM
148 | Implementation-Title: git
149 | Implementation-Version: 2.0.1
150 | Group-Id: org.jenkins-ci.plugins
151 | Short-Name: git
152 | Long-Name: Jenkins GIT plugin
153 | Url: http://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin
154 | Plugin-Version: 2.0.1
155 | Hudson-Version: 1.480
156 | Jenkins-Version: 1.480
157 | Plugin-Dependencies: promoted-builds:2.7;resolution:=optional,token-ma
158 | cro:1.5.1;resolution:=optional,ssh-credentials:1.5.1,scm-api:0.1,cred
159 | entials:1.9.3,multiple-scms:0.2;resolution:=optional,parameterized-tr
160 | igger:2.4;resolution:=optional,git-client:1.6.0
161 | Plugin-Developers: Kohsuke Kawaguchi:kohsuke:,Nicolas De Loof:ndeloof:
162 | nicolas.deloof@gmail.com
163 |
164 | '
165 | end
166 |
167 | it { is_expected.to be_instance_of Hash }
168 |
169 | it 'has the right number of keys' do
170 | expect(data.keys.size).to be(18)
171 | end
172 | end
173 | end
174 | end
175 |
--------------------------------------------------------------------------------
/spec/unit/jenkins_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'puppet/jenkins'
5 |
6 | describe Puppet::Jenkins do
7 | describe '.home_dir' do
8 | subject(:home_dir) { described_class.home_dir }
9 |
10 | context "when a jenkins user doesn't exist" do
11 | before do
12 | expect(File).to receive(:expand_path).and_raise(ArgumentError)
13 | end
14 |
15 | it { is_expected.to be_nil }
16 | end
17 |
18 | context 'when a jenkins user does exist' do
19 | let(:home) { '/rspec/jenkins' }
20 |
21 | before do
22 | expect(File).to receive(:expand_path).and_return(home)
23 | end
24 |
25 | it { is_expected.to eql home }
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/unit/puppet/provider/jenkins_authorization_strategy/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'json'
5 |
6 | describe Puppet::Type.type(:jenkins_authorization_strategy).provider(:cli) do
7 | let(:strategy_oauth_json) do
8 | <<-EOS
9 | {
10 | "setAuthorizationStrategy": {
11 | "org.jenkinsci.plugins.GithubAuthorizationStrategy": [
12 | "jhoblitt, dne",
13 | false,
14 | false,
15 | false,
16 | "lsst, sqre-test",
17 | false,
18 | false,
19 | false
20 | ]
21 | }
22 | }
23 | EOS
24 | end
25 | let(:strategy_oauth) { JSON.parse(strategy_oauth_json) }
26 |
27 | let(:strategy_unsecured_json) do
28 | <<-EOS
29 | {
30 | "setAuthorizationStrategy": {
31 | "hudson.security.AuthorizationStrategy$Unsecured": [
32 |
33 | ]
34 | }
35 | }
36 | EOS
37 | end
38 | let(:strategy_unsecured) { JSON.parse(strategy_unsecured_json) }
39 |
40 | shared_examples 'a provider from example strategy' do
41 | it do
42 | method_name = 'setAuthorizationStrategy'
43 | class_name = info[method_name].keys.first
44 | ctor_args = info[method_name][class_name]
45 |
46 | expect(provider.name).to eq class_name
47 | expect(provider.ensure).to eq :present
48 | expect(provider.arguments).to eq ctor_args
49 | end
50 | end
51 |
52 | describe '::instances' do
53 | context 'without any params' do
54 | before do
55 | expect(described_class).to receive(:get_authorization_strategy).
56 | with(nil) { strategy_oauth }
57 | end
58 |
59 | it 'returns the correct number of instances' do
60 | expect(described_class.instances.size).to eq 1
61 | end
62 |
63 | context 'first instance returned' do
64 | it_behaves_like 'a provider from example strategy' do
65 | let(:info) { strategy_oauth }
66 | let(:provider) { described_class.instances[0] }
67 | end
68 | end
69 | end
70 |
71 | context 'when called with a catalog param' do
72 | it 'passes it on ::get_authorization_strategy' do
73 | catalog = Puppet::Resource::Catalog.new
74 |
75 | expect(described_class).to receive(:get_authorization_strategy).
76 | with(catalog) { strategy_oauth }
77 |
78 | described_class.instances(catalog)
79 | end
80 | end
81 | end
82 |
83 | describe '#flush' do
84 | it 'calls set_jenkins_instance' do
85 | provider = described_class.new
86 | provider.create
87 |
88 | expect(provider).to receive(:set_jenkins_instance)
89 | provider.flush
90 | end
91 |
92 | it 'calls set_strategy_unsecured' do
93 | provider = described_class.new
94 | provider.destroy
95 |
96 | expect(provider).to receive(:set_strategy_unsecured)
97 | provider.flush
98 | end
99 |
100 | it 'calls set_strategy_unsecured' do
101 | provider = described_class.new
102 |
103 | expect(provider).to receive(:set_strategy_unsecured)
104 | provider.flush
105 | end
106 | end
107 |
108 | #
109 | # private methods
110 | #
111 |
112 | describe '::from_hash' do
113 | it_behaves_like 'a provider from example strategy' do
114 | let(:info) { strategy_oauth }
115 | let(:provider) { described_class.send(:from_hash, info) }
116 | end
117 |
118 | it_behaves_like 'a provider from example strategy' do
119 | let(:info) { strategy_unsecured }
120 | let(:provider) { described_class.send(:from_hash, info) }
121 | end
122 | end
123 |
124 | describe '::to_hash' do
125 | # not isolated from ::from_hash in the interests of staying DRY
126 | it do
127 | provider = described_class.send :from_hash, strategy_oauth
128 | info = provider.send :to_hash
129 |
130 | expect(info).to eq strategy_oauth
131 | end
132 | end
133 |
134 | describe '::get_authorization_strategy' do
135 | it do
136 | expect(described_class).to receive(:clihelper).with(
137 | ['get_authorization_strategy'],
138 | catalog: nil
139 | ) { strategy_oauth_json }
140 |
141 | raw = described_class.send :get_authorization_strategy
142 | expect(raw).to eq strategy_oauth
143 | end
144 | end
145 |
146 | describe '#set_jenkins_instance' do
147 | it do
148 | provider = described_class.send :from_hash, strategy_oauth
149 |
150 | expect(described_class).to receive(:clihelper).with(
151 | ['set_jenkins_instance'],
152 | stdinjson: strategy_oauth
153 | )
154 |
155 | provider.send :set_jenkins_instance
156 | end
157 | end
158 |
159 | describe '#set_strategy_unsecured' do
160 | it do
161 | provider = described_class.new(name: 'test')
162 |
163 | expect(described_class).to receive(:clihelper).with(
164 | ['set_jenkins_instance'],
165 | stdinjson: strategy_unsecured
166 | )
167 |
168 | provider.send :set_strategy_unsecured
169 | end
170 | end
171 | end
172 |
--------------------------------------------------------------------------------
/spec/unit/puppet/provider/jenkins_num_executors/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'json'
5 |
6 | describe Puppet::Type.type(:jenkins_num_executors).provider(:cli) do
7 | describe '::instances' do
8 | context 'without any params' do
9 | before do
10 | expect(described_class).to receive(:get_num_executors).
11 | with(nil).and_return(42)
12 | end
13 |
14 | it 'returns the correct number of instances' do
15 | expect(described_class.instances.size).to eq 1
16 | end
17 |
18 | context 'first instance returned' do
19 | let(:provider) { described_class.instances[0] }
20 |
21 | it { expect(provider.name).to eq 42 }
22 | end
23 | end
24 |
25 | context 'when called with a catalog param' do
26 | it 'passes it on ::get_num_executors' do
27 | catalog = Puppet::Resource::Catalog.new
28 |
29 | expect(described_class).to receive(:get_num_executors).
30 | with(catalog).and_return(42)
31 |
32 | described_class.instances(catalog)
33 | end
34 | end
35 | end
36 |
37 | describe '#flush' do
38 | it 'calls set_num_executors' do
39 | provider = described_class.new
40 | provider.create
41 |
42 | expect(provider).to receive(:set_num_executors).with(no_args)
43 | provider.flush
44 | end
45 |
46 | it 'fails' do
47 | provider = described_class.new
48 | provider.destroy
49 |
50 | expect { provider.flush }.
51 | to raise_error(Puppet::Error, %r{invalid :ensure value: absent})
52 | end
53 | end
54 |
55 | #
56 | # private methods
57 | #
58 |
59 | describe '::get_num_executors' do
60 | it do
61 | expect(described_class).to receive(:clihelper).
62 | with(['get_num_executors'], catalog: nil).and_return(42)
63 |
64 | n = described_class.send :get_num_executors
65 | expect(n).to eq 42
66 | end
67 | end
68 |
69 | describe '#set_jenkins_instance' do
70 | it do
71 | provider = described_class.new(name: 42)
72 |
73 | expect(described_class).to receive(:clihelper).with(['set_num_executors', 42])
74 |
75 | provider.send :set_num_executors
76 | end
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/spec/unit/puppet/provider/jenkins_security_realm/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'json'
5 |
6 | describe Puppet::Type.type(:jenkins_security_realm).provider(:cli) do
7 | let(:realm_oauth_json) do
8 | <<-EOS
9 | {
10 | "setSecurityRealm": {
11 | "org.jenkinsci.plugins.GithubSecurityRealm": [
12 | "https://github.com",
13 | "https://api.github.com",
14 | "42",
15 | "43",
16 | "read:org"
17 | ]
18 | }
19 | }
20 | EOS
21 | end
22 | let(:realm_oauth) { JSON.parse(realm_oauth_json) }
23 |
24 | let(:realm_none_json) do
25 | <<-EOS
26 | {
27 | "setSecurityRealm": {
28 | "hudson.security.SecurityRealm$None": [
29 |
30 | ]
31 | }
32 | }
33 | EOS
34 | end
35 | let(:realm_none) { JSON.parse(realm_none_json) }
36 |
37 | shared_examples 'a provider from example realm' do
38 | it do
39 | method_name = 'setSecurityRealm'
40 | class_name = info[method_name].keys.first
41 | ctor_args = info[method_name][class_name]
42 |
43 | expect(provider.name).to eq class_name
44 | expect(provider.ensure).to eq :present
45 | expect(provider.arguments).to eq ctor_args
46 | end
47 | end
48 |
49 | describe '::instances' do
50 | context 'without any params' do
51 | before do
52 | expect(described_class).to receive(:get_security_realm).
53 | with(nil) { realm_oauth }
54 | end
55 |
56 | it 'returns the correct number of instances' do
57 | expect(described_class.instances.size).to eq 1
58 | end
59 |
60 | context 'first instance returned' do
61 | it_behaves_like 'a provider from example realm' do
62 | let(:info) { realm_oauth }
63 | let(:provider) { described_class.instances[0] }
64 | end
65 | end
66 | end
67 |
68 | context 'when called with a catalog param' do
69 | it 'passes it on ::get_security_realm' do
70 | catalog = Puppet::Resource::Catalog.new
71 |
72 | expect(described_class).to receive(:get_security_realm).
73 | with(catalog) { realm_oauth }
74 |
75 | described_class.instances(catalog)
76 | end
77 | end
78 | end
79 |
80 | describe '#flush' do
81 | it 'calls set_jenkins_instance' do
82 | provider = described_class.new
83 | provider.create
84 |
85 | expect(provider).to receive(:set_jenkins_instance)
86 | provider.flush
87 | end
88 |
89 | it 'calls set_security_none' do
90 | provider = described_class.new
91 | provider.destroy
92 |
93 | expect(provider).to receive(:set_security_none)
94 | provider.flush
95 | end
96 |
97 | it 'calls set_security_none' do
98 | provider = described_class.new
99 |
100 | expect(provider).to receive(:set_security_none)
101 | provider.flush
102 | end
103 | end
104 |
105 | #
106 | # private methods
107 | #
108 |
109 | describe '::from_hash' do
110 | it_behaves_like 'a provider from example realm' do
111 | let(:info) { realm_oauth }
112 | let(:provider) { described_class.send(:from_hash, info) }
113 | end
114 |
115 | it_behaves_like 'a provider from example realm' do
116 | let(:info) { realm_none }
117 | let(:provider) { described_class.send(:from_hash, info) }
118 | end
119 | end
120 |
121 | describe '::to_hash' do
122 | # not isolated from ::from_hash in the interests of staying DRY
123 | it do
124 | provider = described_class.send :from_hash, realm_oauth
125 | info = provider.send :to_hash
126 |
127 | expect(info).to eq realm_oauth
128 | end
129 | end
130 |
131 | describe '::get_security_realm' do
132 | # not isolated from ::from_hash in the interests of staying DRY
133 | it do
134 | expect(described_class).to receive(:clihelper).with(
135 | ['get_security_realm'],
136 | catalog: nil
137 | ) { realm_oauth_json }
138 |
139 | raw = described_class.send :get_security_realm
140 | expect(raw).to eq realm_oauth
141 | end
142 | end
143 |
144 | describe '#set_jenkins_instance' do
145 | it do
146 | provider = described_class.send :from_hash, realm_oauth
147 |
148 | expect(described_class).to receive(:clihelper).with(
149 | ['set_jenkins_instance'],
150 | stdinjson: realm_oauth
151 | )
152 |
153 | provider.send :set_jenkins_instance
154 | end
155 | end
156 |
157 | describe '#set_security_none' do
158 | it do
159 | provider = described_class.new(name: 'test')
160 |
161 | expect(described_class).to receive(:clihelper).with(
162 | ['set_jenkins_instance'],
163 | stdinjson: realm_none
164 | )
165 |
166 | provider.send :set_security_none
167 | end
168 | end
169 | end
170 |
--------------------------------------------------------------------------------
/spec/unit/puppet/provider/jenkins_slaveagent_port/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'json'
5 |
6 | describe Puppet::Type.type(:jenkins_slaveagent_port).provider(:cli) do
7 | describe '::instances' do
8 | context 'without any params' do
9 | before do
10 | expect(described_class).to receive(:get_slaveagent_port).
11 | with(nil).and_return(42)
12 | end
13 |
14 | it 'returns the correct number of instances' do
15 | expect(described_class.instances.size).to eq 1
16 | end
17 |
18 | context 'first instance returned' do
19 | let(:provider) { described_class.instances[0] }
20 |
21 | it { expect(provider.name).to eq 42 }
22 | end
23 | end
24 |
25 | context 'when called with a catalog param' do
26 | it 'passes it on ::get_slaveagent_port' do
27 | catalog = Puppet::Resource::Catalog.new
28 |
29 | expect(described_class).to receive(:get_slaveagent_port).
30 | with(catalog).and_return(42)
31 |
32 | described_class.instances(catalog)
33 | end
34 | end
35 | end
36 |
37 | describe '#flush' do
38 | it 'calls set_slaveagent_port' do
39 | provider = described_class.new
40 | provider.create
41 |
42 | expect(provider).to receive(:set_slaveagent_port).with(no_args)
43 | provider.flush
44 | end
45 |
46 | it 'fails' do
47 | provider = described_class.new
48 | provider.destroy
49 |
50 | expect { provider.flush }.
51 | to raise_error(Puppet::Error, %r{invalid :ensure value: absent})
52 | end
53 | end
54 |
55 | #
56 | # private methods
57 | #
58 |
59 | describe '::get_slaveagent_port' do
60 | it do
61 | expect(described_class).to receive(:clihelper).
62 | with(['get_slaveagent_port'], catalog: nil).and_return(42)
63 |
64 | n = described_class.send :get_slaveagent_port
65 | expect(n).to eq 42
66 | end
67 | end
68 |
69 | describe '#set_jenkins_instance' do
70 | it do
71 | provider = described_class.new(name: 42)
72 |
73 | expect(described_class).to receive(:clihelper).with(['set_slaveagent_port', 42])
74 |
75 | provider.send :set_slaveagent_port
76 | end
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/spec/unit/puppet/provider/jenkins_user/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_providers'
5 |
6 | require 'json'
7 |
8 | describe Puppet::Type.type(:jenkins_user).provider(:cli) do
9 | let(:user_info_json) do
10 | <<-EOS
11 | [
12 | {
13 |
14 | "id": "test",
15 | "full_name": "test",
16 | "email_address": "foo@foo.org",
17 | "public_keys": ["ssh-rsa foo com", "ssh-rsa bar com"],
18 | "api_token_public": "b0da1e0bf3f79ff02624c2f716913808",
19 | "api_token_plain": "51a8b1dd95bc76b1a2869356c043e8b9",
20 | "password": "#jbcrypt:$2a$10$dg5kqB/bNVgotE0alN.V5OQJ1BajkmM2ZOFAmtlSt29bB4xEDZOja"
21 | },
22 | {
23 | "id": "guest"
24 | }
25 | ]
26 | EOS
27 | end
28 | let(:user_info) { JSON.parse(user_info_json) }
29 | let(:mutable_user_info) do
30 | # we should not be trying to flush the api_token_public value as it is
31 | # immutable
32 | info = user_info[0]
33 | info.delete('api_token_public')
34 | info
35 | end
36 |
37 | shared_examples 'a provider from example hash 1' do
38 | it do
39 | expect(provider.name).to eq user_info[0]['id']
40 | expect(provider.ensure).to eq :present
41 | expect(provider.full_name).to eq user_info[0]['full_name']
42 | expect(provider.email_address).to eq user_info[0]['email_address']
43 | expect(provider.public_keys).to eq user_info[0]['public_keys']
44 | expect(provider.api_token_public).to eq user_info[0]['api_token_public']
45 | expect(provider.api_token_plain).to eq user_info[0]['api_token_plain']
46 | expect(provider.password).to eq user_info[0]['password']
47 | end
48 | end
49 |
50 | shared_examples 'a provider from example hash 2' do
51 | it do
52 | expect(provider.name).to eq user_info[1]['id']
53 | expect(provider.ensure).to eq :present
54 | expect(provider.full_name).to eq :absent
55 | expect(provider.email_address).to eq :absent
56 | expect(provider.public_keys).to eq :absent
57 | expect(provider.api_token_public).to eq :absent
58 | expect(provider.api_token_plain).to eq :absent
59 | expect(provider.password).to eq :absent
60 | end
61 | end
62 |
63 | include_examples 'confines to cli dependencies'
64 |
65 | describe '::instances' do
66 | context 'without any params' do
67 | before do
68 | expect(described_class).to receive(:user_info_all).
69 | with(nil) { user_info }
70 | end
71 |
72 | it 'returns the correct number of instances' do
73 | expect(described_class.instances.size).to eq 2
74 | end
75 |
76 | context 'first instance returned' do
77 | it_behaves_like 'a provider from example hash 1' do
78 | let(:provider) do
79 | described_class.instances[0]
80 | end
81 | end
82 | end
83 |
84 | context 'second instance returned' do
85 | it_behaves_like 'a provider from example hash 2' do
86 | let(:provider) do
87 | described_class.instances[1]
88 | end
89 | end
90 | end
91 | end
92 |
93 | context 'when called with a catalog param' do
94 | it 'passes it on ::user_info_all' do
95 | catalog = Puppet::Resource::Catalog.new
96 |
97 | expect(described_class).to receive(:user_info_all).
98 | with(catalog) { user_info }
99 |
100 | described_class.instances(catalog)
101 | end
102 | end
103 | end
104 |
105 | describe '#api_token_public=' do
106 | it 'is read only (fail)' do
107 | provider = described_class.new
108 |
109 | expect { provider.api_token_public = 'foo' }.to raise_error(Puppet::Error, %r{api_token_public is read-only})
110 | end
111 | end
112 |
113 | describe '#flush' do
114 | it 'calls user_update' do
115 | provider = described_class.new
116 | provider.create
117 |
118 | expect(provider).to receive(:user_update)
119 | provider.flush
120 | end
121 |
122 | it 'calls delete_user' do
123 | provider = described_class.new
124 | provider.destroy
125 |
126 | expect(provider).to receive(:delete_user)
127 | provider.flush
128 | end
129 |
130 | it 'calls delete_user' do
131 | provider = described_class.new
132 |
133 | expect(provider).to receive(:delete_user)
134 | provider.flush
135 | end
136 | end
137 |
138 | #
139 | # private methods
140 | #
141 |
142 | describe '::from_hash' do
143 | it_behaves_like 'a provider from example hash 1' do
144 | let(:provider) do
145 | described_class.send :from_hash, user_info[0]
146 | end
147 | end
148 |
149 | it_behaves_like 'a provider from example hash 2' do
150 | let(:provider) do
151 | described_class.send :from_hash, user_info[1]
152 | end
153 | end
154 | end
155 |
156 | describe '::to_hash' do
157 | # not isolated from ::from_hash in the interests of staying DRY
158 | it do
159 | provider = described_class.send :from_hash, user_info[0]
160 | info = provider.send :to_hash
161 |
162 | expect(info).to eq mutable_user_info
163 | end
164 | end
165 |
166 | describe '::user_info_all' do
167 | # not isolated from ::from_hash in the interests of staying DRY
168 | it do
169 | expect(described_class).to receive(:clihelper).with(['user_info_all']) { user_info_json }
170 |
171 | raw = described_class.send :user_info_all
172 | expect(raw).to eq user_info
173 | end
174 | end
175 |
176 | describe '#user_update' do
177 | RSpec::Matchers.define :a_json_doc do |x|
178 | match { |actual| JSON.parse(actual) == x }
179 | end
180 |
181 | it do
182 | provider = described_class.send :from_hash, user_info[0]
183 |
184 | expect(described_class).to receive(:clihelper).with(
185 | ['user_update'],
186 | stdinjson: mutable_user_info
187 | )
188 |
189 | provider.send :user_update
190 | end
191 | end
192 |
193 | describe '#delete_user' do
194 | it do
195 | provider = described_class.send :from_hash, user_info[0]
196 |
197 | expect(described_class).to receive(:clihelper).with(
198 | %w[delete_user test]
199 | )
200 |
201 | provider.send :delete_user
202 | end
203 | end
204 | end
205 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_authorization_strategy_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_authorization_strategy) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 | end
14 |
15 | describe 'properties' do
16 | describe 'ensure' do
17 | it_behaves_like 'generic ensurable'
18 | end
19 |
20 | describe 'arguments' do
21 | it_behaves_like 'array_matching property'
22 | end
23 | end
24 |
25 | describe 'autorequire' do
26 | it_behaves_like 'autorequires cli resources'
27 | it_behaves_like 'autorequires all jenkins_user resources'
28 | it_behaves_like 'autorequires jenkins_security_realm resource'
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_credentials_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_credentials) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 | end
14 |
15 | describe 'properties' do
16 | describe 'ensure' do
17 | it_behaves_like 'generic ensurable'
18 | end
19 |
20 | describe 'domain' do
21 | it_behaves_like 'validated property', :domain, :undef, [:undef]
22 | end
23 |
24 | describe 'scope' do
25 | it_behaves_like 'validated property', :scope, :GLOBAL, %i[GLOBAL SYSTEM]
26 | end
27 |
28 | describe 'impl' do
29 | it_behaves_like 'validated property', :impl,
30 | :UsernamePasswordCredentialsImpl,
31 | %i[
32 | UsernamePasswordCredentialsImpl
33 | BasicSSHUserPrivateKey
34 | StringCredentialsImpl
35 | FileCredentialsImpl
36 | AWSCredentialsImpl
37 | GitLabApiTokenImpl
38 | BrowserStackCredentials
39 | ]
40 | end
41 |
42 | # unvalidated properties
43 | %i[
44 | description
45 | username
46 | password
47 | private_key
48 | passphrase
49 | secret
50 | file_name
51 | content
52 | source
53 | key_store_impl
54 | secret_key
55 | access_key
56 | api_token
57 | ].each do |property|
58 | describe property.to_s do
59 | context 'attrtype' do
60 | it { expect(described_class.attrtype(property)).to eq :property }
61 | end
62 | end
63 | end
64 | end
65 |
66 | describe 'autorequire' do
67 | it_behaves_like 'autorequires cli resources'
68 | it_behaves_like 'autorequires all jenkins_user resources'
69 | it_behaves_like 'autorequires jenkins_security_realm resource'
70 | it_behaves_like 'autorequires jenkins_authorization_strategy resource'
71 | end
72 | end
73 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_job_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_job) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 |
14 | describe 'show_diff' do
15 | it_behaves_like 'boolean parameter', :show_diff, true
16 | end
17 | end
18 |
19 | describe 'properties' do
20 | describe 'ensure' do
21 | it_behaves_like 'generic ensurable'
22 | end
23 |
24 | describe 'enable' do
25 | it_behaves_like 'boolean property', :enable, true
26 | end
27 |
28 | describe 'replace' do
29 | it_behaves_like 'boolean parameter', :replace, true
30 | end
31 |
32 | describe 'config' do
33 | let(:resource) { described_class.new(name: 'foo', config: 'bar') }
34 | let(:property) { resource.property(:config) }
35 |
36 | it { expect(described_class.attrtype(:config)).to eq :property }
37 |
38 | [true, false].product([true, false]).each do |cfg, param|
39 | describe "and Puppet[:show_diff] is #{cfg} and show_diff => #{param}" do
40 | before do
41 | Puppet[:show_diff] = cfg
42 | resource[:show_diff] = param
43 | resource[:loglevel] = 'debug'
44 | end
45 |
46 | if cfg && param
47 | it 'displays a diff' do
48 | expect(property).to receive(:diff).once.and_return('foo')
49 | property.change_to_s('foo', 'bar')
50 | end
51 | else
52 | it 'does not display a diff' do
53 | expect(property).not_to receive :diff
54 | property.change_to_s('foo', 'bar')
55 | end
56 | end
57 | end
58 | end
59 |
60 | describe 'change_to_s change string' do
61 | context 'created' do
62 | it { expect(property.change_to_s(:absent, nil)).to eq 'created' }
63 | end
64 |
65 | context 'removed' do
66 | it { expect(property.change_to_s(nil, :absent)).to eq 'removed' }
67 | end
68 |
69 | context 'changed with replace' do
70 | it do
71 | expect(property.change_to_s('foo', 'bar')).
72 | to match(%r{content changed '{md5}\w+' to '{md5}\w+'})
73 | end
74 | end
75 |
76 | context 'changed without replace' do
77 | let(:resource) { described_class.new(name: 'foo', config: 'bar', replace: false) }
78 |
79 | it { expect(property.change_to_s('foo', 'bar')).to eq 'left unchanged' }
80 | end
81 | end
82 | end
83 | end
84 |
85 | describe 'autorequire' do
86 | it_behaves_like 'autorequires cli resources'
87 | it_behaves_like 'autorequires all jenkins_user resources'
88 | it_behaves_like 'autorequires jenkins_security_realm resource'
89 | it_behaves_like 'autorequires jenkins_authorization_strategy resource'
90 |
91 | describe 'folders' do
92 | it 'autorequires parent folder resource' do
93 | folder = described_class.new(
94 | name: 'foo'
95 | )
96 |
97 | job = described_class.new(
98 | name: 'foo/bar'
99 | )
100 |
101 | folder[:ensure] = :present
102 | job[:ensure] = :present
103 |
104 | catalog = Puppet::Resource::Catalog.new
105 | catalog.add_resource folder
106 | catalog.add_resource job
107 | req = job.autorequire
108 |
109 | expect(req.size).to eq 1
110 | expect(req[0].source).to eq folder
111 | expect(req[0].target).to eq job
112 | end
113 |
114 | it 'autorequires multiple nested parent folder resources' do
115 | folder1 = described_class.new(
116 | name: 'foo'
117 | )
118 |
119 | folder2 = described_class.new(
120 | name: 'foo/bar'
121 | )
122 |
123 | job = described_class.new(
124 | name: 'foo/bar/baz'
125 | )
126 |
127 | folder1[:ensure] = :present
128 | folder2[:ensure] = :present
129 | job[:ensure] = :present
130 |
131 | catalog = Puppet::Resource::Catalog.new
132 | catalog.add_resource folder1
133 | catalog.add_resource folder2
134 | catalog.add_resource job
135 | req = job.autorequire
136 |
137 | expect(req.size).to eq 2
138 | expect(req[0].source).to eq folder1
139 | expect(req[0].target).to eq job
140 | expect(req[1].source).to eq folder2
141 | expect(req[1].target).to eq job
142 | end
143 |
144 | it 'autobefores multiple nested parent folder resources',
145 | unless: Puppet.version.to_f < 4.0 do
146 | folder1 = described_class.new(
147 | name: 'foo'
148 | )
149 |
150 | folder2 = described_class.new(
151 | name: 'foo/bar'
152 | )
153 |
154 | job = described_class.new(
155 | name: 'foo/bar/baz'
156 | )
157 |
158 | folder1[:ensure] = :absent
159 | folder2[:ensure] = :absent
160 | job[:ensure] = :absent
161 |
162 | catalog = Puppet::Resource::Catalog.new
163 | catalog.add_resource folder1
164 | catalog.add_resource folder2
165 | catalog.add_resource job
166 | req = job.autobefore
167 |
168 | expect(req.size).to eq 2
169 | expect(req[0].source).to eq job
170 | expect(req[0].target).to eq folder1
171 | expect(req[1].source).to eq job
172 | expect(req[1].target).to eq folder2
173 | end
174 | end
175 | end
176 | end
177 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_num_executors_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_num_executors) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 | end
14 |
15 | describe 'properties' do
16 | describe 'ensure' do
17 | it_behaves_like 'generic ensurable', :present
18 | end
19 | end
20 |
21 | describe 'autorequire' do
22 | it_behaves_like 'autorequires cli resources'
23 | it_behaves_like 'autorequires all jenkins_user resources'
24 | it_behaves_like 'autorequires jenkins_security_realm resource'
25 | it_behaves_like 'autorequires jenkins_authorization_strategy resource'
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_security_realm_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_security_realm) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 | end
14 |
15 | describe 'properties' do
16 | describe 'ensure' do
17 | it_behaves_like 'generic ensurable'
18 | end
19 |
20 | describe 'arguments' do
21 | it_behaves_like 'array_matching property'
22 | end
23 | end
24 |
25 | describe 'autorequire' do
26 | it_behaves_like 'autorequires cli resources'
27 | it_behaves_like 'autorequires all jenkins_user resources'
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_slaveagent_port_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_slaveagent_port) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 | end
14 |
15 | describe 'properties' do
16 | describe 'ensure' do
17 | it_behaves_like 'generic ensurable', :present
18 | end
19 | end
20 |
21 | describe 'autorequire' do
22 | it_behaves_like 'autorequires cli resources'
23 | it_behaves_like 'autorequires all jenkins_user resources'
24 | it_behaves_like 'autorequires jenkins_security_realm resource'
25 | it_behaves_like 'autorequires jenkins_authorization_strategy resource'
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/unit/puppet/type/jenkins_user_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | describe Puppet::Type.type(:jenkins_user) do
7 | before { Facter.clear }
8 |
9 | describe 'parameters' do
10 | describe 'name' do
11 | it_behaves_like 'generic namevar', :name
12 | end
13 | end
14 |
15 | describe 'properties' do
16 | describe 'ensure' do
17 | it_behaves_like 'generic ensurable'
18 | end
19 |
20 | # unvalidated properties
21 | %i[full_name email_address
22 | api_token_public password].each do |property|
23 | describe property.to_s do
24 | it { expect(described_class.attrtype(property)).to eq :property }
25 | end
26 | end
27 |
28 | describe 'api_token_plain' do
29 | it { expect(described_class.attrtype(:api_token_plain)).to eq :property }
30 |
31 | it 'supports valid hexstrings' do
32 | value = '51a8b1dd95bc76b1a2869356c043e8b9'
33 | expect do
34 | described_class.new(
35 | name: 'nobody',
36 | api_token_plain: value
37 | )
38 | end.
39 | not_to raise_error
40 | end
41 |
42 | %w[ 51a8b1dd95bc76b1a2869356c043e8b
43 | 51a8b1dd95bc76b1a2869356c043e8b99 ].each do |value|
44 | it 'rejects hexstrings of invalid length' do
45 | expect do
46 | described_class.new(
47 | name: 'nobody',
48 | api_token_plain: value
49 | )
50 | end.
51 | to raise_error(Puppet::ResourceError, %r{is not a 32char hex string})
52 | end
53 | end
54 | end
55 |
56 | describe 'public_keys' do
57 | it { expect(described_class.attrtype(:public_keys)).to eq :property }
58 |
59 | it 'supports single string' do
60 | value = 'ssh-rsa blah comment'
61 | user = described_class.new(name: 'nobody', public_keys: value)
62 | expect(user[:public_keys]).to eq [value]
63 | end
64 |
65 | it 'supports array of string' do
66 | value = ['ssh-rsa blah comment', 'ssh-rsa foo comment']
67 | user = described_class.new(name: 'nobody', public_keys: value)
68 | expect(user[:public_keys]).to eq value
69 | end
70 | end
71 | end
72 |
73 | describe 'autorequire' do
74 | it_behaves_like 'autorequires cli resources'
75 | end
76 | end
77 |
--------------------------------------------------------------------------------
/spec/unit/puppet/x/jenkins/config_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | require 'puppet/x/jenkins/config'
6 |
7 | describe Puppet::X::Jenkins::Config do
8 | DEFAULTS = {
9 | cli_jar: '/usr/share/java/jenkins-cli.jar',
10 | url: 'http://localhost:8080',
11 | ssh_private_key: nil,
12 | puppet_helper: '/usr/share/java/puppet_helper.groovy',
13 | cli_tries: 30
14 | }.freeze
15 |
16 | shared_context 'facts' do
17 | before do
18 | Facter.add(:jenkins_cli_jar) { setcode { 'fact.jar' } }
19 | Facter.add(:jenkins_url) { setcode { 'http://localhost:11' } }
20 | Facter.add(:jenkins_ssh_private_key) { setcode { 'fact.id_rsa' } }
21 | Facter.add(:jenkins_puppet_helper) { setcode { 'fact.groovy' } }
22 | Facter.add(:jenkins_cli_tries) { setcode { 22 } }
23 | end
24 | end
25 |
26 | shared_examples 'returns default values' do |_param|
27 | it 'returns default values' do
28 | DEFAULTS.each do |k, v|
29 | expect(config[k]).to eq v
30 | end
31 | end
32 | end
33 |
34 | shared_examples 'returns fact values' do |_param|
35 | it 'returns fact values' do
36 | DEFAULTS.each_key do |k|
37 | expect(config[k]).to eq Facter.value("jenkins_#{k}".to_sym)
38 | end
39 | end
40 | end
41 |
42 | shared_examples 'returns catalog values' do |_param|
43 | it 'returns catalog values' do
44 | config = catalog.resource(:class, 'jenkins::cli::config')
45 |
46 | DEFAULTS.each_key do |k|
47 | expect(config[k]).not_to be_nil
48 | end
49 | end
50 | end
51 |
52 | before { Facter.clear }
53 |
54 | # we are relying on a side effect of this method being to test features /
55 | # load libs
56 | describe '#initialize' do
57 | it { expect(described_class.new).to be_a described_class }
58 | end
59 |
60 | describe '#[]' do
61 | context 'unknown config key' do
62 | it do
63 | expect { described_class.new[:foo] }.
64 | to raise_error(Puppet::X::Jenkins::Config::UnknownConfig)
65 | end
66 | end
67 |
68 | context 'no catalog' do
69 | let(:config) { described_class.new }
70 |
71 | context 'no facts' do
72 | include_examples 'returns default values'
73 | end
74 |
75 | context 'with facts' do
76 | include_examples 'returns fact values' do
77 | include_context 'facts'
78 | end
79 | end
80 | end
81 |
82 | context 'with catalog' do
83 | let(:catalog) { Puppet::Resource::Catalog.new }
84 | let(:config) { described_class.new(catalog) }
85 |
86 | context 'no jenkins::cli::config class' do
87 | context 'no facts' do
88 | include_examples 'returns default values'
89 | end
90 |
91 | context 'with facts' do
92 | include_examples 'returns fact values' do
93 | include_context 'facts'
94 | end
95 | end
96 | end
97 |
98 | context 'with jenkins::cli::config class' do
99 | context 'with no params' do
100 | before do
101 | jenkins = Puppet::Type.type(:component).new(
102 | name: 'jenkins::cli::config'
103 | )
104 |
105 | catalog.add_resource jenkins
106 | end
107 |
108 | context 'no facts' do
109 | include_examples 'returns default values'
110 | end
111 |
112 | context 'with facts' do
113 | include_examples 'returns fact values' do
114 | include_context 'facts'
115 | end
116 | end
117 | end
118 |
119 | context 'with all params' do
120 | before do
121 | jenkins = Puppet::Type.type(:component).new(
122 | name: 'jenkins::cli::config',
123 | cli_jar: 'cat.jar',
124 | url: 'http://localhost:111',
125 | ssh_private_key: 'cat.id_rsa',
126 | puppet_helper: 'cat.groovy',
127 | cli_tries: 222
128 | )
129 |
130 | catalog.add_resource jenkins
131 | end
132 |
133 | context 'no facts' do
134 | include_examples 'returns catalog values'
135 | end
136 |
137 | context 'with facts' do
138 | include_examples 'returns catalog values' do
139 | include_context 'facts'
140 | end
141 | end
142 | end
143 | end
144 | end
145 | end
146 | end
147 |
--------------------------------------------------------------------------------
/spec/unit/puppet/x/jenkins/type/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'unit/puppet/x/spec_jenkins_types'
5 |
6 | require 'puppet/x/jenkins/type/cli'
7 |
8 | Puppet::X::Jenkins::Type::Cli.newtype(:test) do
9 | newparam(:foo) { isnamevar }
10 | end
11 |
12 | describe Puppet::Type.type(:test) do
13 | describe 'autorequire' do
14 | it_behaves_like 'autorequires cli resources'
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/unit/puppet/x/jenkins/util_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | require 'puppet/x/jenkins/util'
6 |
7 | describe Puppet::X::Jenkins::Util do
8 | let(:data) do
9 | {
10 | a: :undef,
11 | b: [
12 | nil,
13 | 1,
14 | {
15 | c: nil,
16 | d: [
17 | :undef,
18 | 1
19 | ],
20 | e: 1
21 | }
22 | ],
23 | f: 1
24 | }
25 | end
26 |
27 | describe '::unundef' do
28 | it 'converts :undef values to nil' do
29 | expect(described_class.unundef(data)).to eq(a: nil,
30 | b: [
31 | nil,
32 | 1,
33 | {
34 | c: nil,
35 | d: [
36 | nil,
37 | 1
38 | ],
39 | e: 1
40 | }
41 | ],
42 | f: 1)
43 | end
44 | end
45 |
46 | describe '::undefize' do
47 | it 'converts nil values to :undef' do
48 | expect(described_class.undefize(data)).to eq(a: :undef,
49 | b: [
50 | :undef,
51 | 1,
52 | {
53 | c: :undef,
54 | d: [
55 | :undef,
56 | 1
57 | ],
58 | e: 1
59 | }
60 | ],
61 | f: 1)
62 | end
63 | end
64 |
65 | describe '::iterate' do
66 | it 'does not transform without block' do
67 | expect(described_class.iterate(data)).to eq(data)
68 | end
69 |
70 | it 'does not affect hash keys' do
71 | expect(described_class.iterate(data) { 5 }).to eq(a: 5,
72 | b: [
73 | 5,
74 | 5,
75 | {
76 | c: 5,
77 | d: [
78 | 5,
79 | 5
80 | ],
81 | e: 5
82 | }
83 | ],
84 | f: 5)
85 | end
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/spec/unit/puppet/x/spec_jenkins_providers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | shared_examples 'confines to cli dependencies' do
6 | describe 'confine' do
7 | let(:confines) do
8 | described_class.confine_collection.instance_variable_get(:@confines)
9 | end
10 |
11 | context 'commands :java' do
12 | it do
13 | expect(confines).to include(
14 | be_a(Puppet::Confine::Exists).
15 | and(have_attributes(values: ['java']))
16 | )
17 | end
18 | end
19 | end
20 |
21 | describe 'commands' do
22 | before do
23 | allow(described_class).to receive(:command).with(:java).and_return('java')
24 | end
25 |
26 | context 'java' do
27 | it { expect(described_class.command(:java)).to eq('java') }
28 | it { expect(described_class).to respond_to(:java) }
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/templates/jenkins-override.epp:
--------------------------------------------------------------------------------
1 | <%- | Hash[String, Struct[{value => Any}]] $environment,
2 | Hash[String[1], String] $dropin_config = {}
3 | | -%>
4 | [Service]
5 | <% $environment.each |$key, $entry| { -%>
6 | Environment="<%= $key %>=<%= $entry['value'] %>"
7 | <% } -%>
8 | <% $dropin_config.each |$key, $value| { -%>
9 | <%= $key %>=<%= $value %>
10 | <% } -%>
11 |
--------------------------------------------------------------------------------
/templates/jenkins-slave-defaults.erb:
--------------------------------------------------------------------------------
1 | # defaults for jenkins slave swarm clients
2 |
3 | # XXX due to the use of conditional statements and variable interpolation,
4 | # this file can not be used in its current state as a systemd EnvironmentFile.
5 |
6 | # location of java
7 | JAVA=<%= @java_cmd %>
8 |
9 | # arguments to pass to java
10 | #JAVA_ARGS="-Xmx256m"
11 | #JAVA_ARGS="-Djava.net.preferIPv4Stack=true" # make jenkins listen on IPv4 address
12 | <% if @java_args.any? -%>
13 | JAVA_ARGS="<%= @java_args.join(' ') -%>"
14 | <% end -%>
15 |
16 | # user id to be invoked as (otherwise will run as root; not wise!)
17 | JENKINS_SLAVE_USER=<%= @slave_user -%>
18 |
19 | # location of the jenkins war file
20 | JENKINS_SLAVE_JAR="<%= @slave_home -%>/<%= @client_jar -%>"
21 |
22 | # log location. this may be a syslog facility.priority
23 | JENKINS_SLAVE_LOG=/var/log/jenkins-slave/jenkins-slave.log
24 |
25 | # slave mode, can be either 'normal' (utilize this slave as much as possible)
26 | # or 'exclusive' (leave this machine for tied jobs only).
27 | JENKINS_SLAVE_MODE=<%= @slave_mode -%>
28 |
29 | # OS LIMITS SETUP
30 | # comment this out to observe /etc/security/limits.conf
31 | # this is on by default because http://github.com/jenkinsci/jenkins/commit/2fb288474e980d0e7ff9c4a3b768874835a3e92e
32 | # reported that Ubuntu's PAM configuration doesn't include pam_limits.so, and as a result the # of file
33 | # descriptors are forced to 1024 regardless of /etc/security/limits.conf
34 | MAXOPENFILES=8192
35 |
36 | MASTER_URL="<%= @masterurl -%>"
37 | AUTO_DISCOVERY_ADDRESS="<%= @autodiscoveryaddress -%>"
38 | LABELS="<%= @labels.join(' ') -%>"
39 |
40 | EXECUTORS=<%= @executors -%>
41 |
42 | CLIENT_NAME="<%= @slave_name -%>"
43 |
44 | FSROOT="<%= @slave_home -%>"
45 |
46 | DESCRIPTION="<%= @description -%>"
47 |
48 | TUNNEL="<%= @tunnel -%>"
49 |
50 | # credentials should be single quoted
51 | JENKINS_USERNAME=<%= @quoted_ui_user %>
52 | JENKINS_PASSWORD=<%= @quoted_ui_pass %>
53 |
54 | OTHER_ARGS="<%= @swarm_client_args.join(' ') %>"
55 |
56 | # boolean; any value but 'true' is considered false
57 | DISABLE_CLIENTS_UNIQUE_ID="<%= 'true' if @disable_clients_unique_id -%>"
58 | DISABLE_SSL_VERIFICATION="<%= 'true' if @disable_ssl_verification -%>"
59 | DELETE_EXISTING_CLIENTS="<%= 'true' if @delete_existing_clients -%>"
60 |
61 | # "= [= ...]"
62 | TOOL_LOCATIONS="<%= @_real_tool_locations %>"
63 |
--------------------------------------------------------------------------------
/templates/jenkins-slave-run.erb:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | fail() {
6 | echo -e "$@"
7 | exit 1
8 | }
9 |
10 | # mandatory input vars
11 | [[ -x "$JAVA" ]] || (fail "$JAVA is not executable")
12 | [[ -f "$JENKINS_SLAVE_JAR" ]] || (fail "$JENKINS_SLAVE_JAR not accessible")
13 |
14 | SLAVE_ARGS=()
15 |
16 | [[ -n "$JAVA_ARGS" ]] &&
17 | SLAVE_ARGS+=("$JAVA_ARGS")
18 |
19 | SLAVE_ARGS+=(-jar "$JENKINS_SLAVE_JAR")
20 |
21 | [[ -n "$JENKINS_SLAVE_MODE" ]] &&
22 | SLAVE_ARGS+=(-mode "$JENKINS_SLAVE_MODE")
23 |
24 | [[ -n "$EXECUTORS" ]] &&
25 | SLAVE_ARGS+=(-executors "$EXECUTORS")
26 |
27 | [[ -n "$JENKINS_USERNAME" ]] &&
28 | SLAVE_ARGS+=(-username "$JENKINS_USERNAME")
29 |
30 | [[ -n "$JENKINS_PASSWORD" ]] &&
31 | SLAVE_ARGS+=(-passwordEnvVariable JENKINS_PASSWORD)
32 |
33 | [[ -n "$CLIENT_NAME" ]] &&
34 | SLAVE_ARGS+=(-name "$CLIENT_NAME")
35 |
36 | [[ -n "$MASTER_URL" ]] &&
37 | SLAVE_ARGS+=(-master "$MASTER_URL")
38 |
39 | [[ -n "$LABELS" ]] &&
40 | SLAVE_ARGS+=(-labels "$LABELS")
41 |
42 | [[ -n "$FSROOT" ]] &&
43 | SLAVE_ARGS+=(-fsroot "$FSROOT")
44 |
45 | [[ "$DISABLE_CLIENTS_UNIQUE_ID" == true ]] &&
46 | SLAVE_ARGS+=(-disableClientsUniqueId)
47 |
48 | [[ "$DISABLE_SSL_VERIFICATION" == true ]] &&
49 | SLAVE_ARGS+=(-disableSslVerification)
50 |
51 | [[ "$DELETE_EXISTING_CLIENTS" == true ]] &&
52 | SLAVE_ARGS+=(-deleteExistingClients)
53 |
54 | [[ -n "$DESCRIPTION" ]] &&
55 | SLAVE_ARGS+=(-description "$DESCRIPTION")
56 |
57 | [[ -n "$TUNNEL" ]] &&
58 | SLAVE_ARGS+=(-tunnel "$TUNNEL")
59 |
60 | [[ -n "$AUTO_DISCOVERY_ADDRESS" ]] &&
61 | SLAVE_ARGS+=(-autoDiscoveryAddress "$AUTO_DISCOVERY_ADDRESS")
62 |
63 | if [ -n "$TOOL_LOCATIONS" ]; then
64 | for t in $TOOL_LOCATIONS; do
65 | SLAVE_ARGS+=(--toolLocation "$t")
66 | done
67 | fi
68 |
69 | [[ -n "$OTHER_ARGS" ]] &&
70 | SLAVE_ARGS+=($OTHER_ARGS)
71 |
72 | $JAVA "${SLAVE_ARGS[@]}"
73 |
--------------------------------------------------------------------------------
/templates/jenkins-slave.service.erb:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Jenkins slave service
3 | Requires=network.target
4 | After=network.target
5 |
6 | [Service]
7 | Type=simple
8 | User=<%= scope['jenkins::slave::slave_user'] %>
9 | EnvironmentFile=<%= scope['jenkins::slave::defaults_location'] %>/jenkins-slave
10 | ExecStart=<%= scope['jenkins::slave::slave_home'] %>/jenkins-slave-run
11 | Restart=always
12 | RestartSec=60
13 | StartLimitInterval=0
14 | SuccessExitStatus=143
15 |
16 | [Install]
17 | WantedBy=multi-user.target
18 |
--------------------------------------------------------------------------------
/templates/org.jenkins-ci.slave.jnlp.plist.epp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <% if $jenkins::slave::quoted_ui_pass { -%>
6 | EnvironmentVariables
7 |
8 | JENKINS_PASSWORD
9 | <%= $jenkins::slave::quoted_ui_pass -%>
10 |
11 | <% } -%>
12 | Label
13 | org.jenkins-ci.slave.jnlp
14 | ProgramArguments
15 |
16 | /usr/bin/java
17 | <% unless empty($jenkins::slave::java_args) { -%>
18 | <%= join($jenkins::slave::java_args, ' ') -%>
19 | <% } -%>
20 | -jar
21 | <%= $jenkins::slave::slave_home -%>/<%= $jenkins::slave::client_jar -%>
22 | <% if $jenkins::slave::slave_mode { -%>
23 | -mode
24 | <%= $jenkins::slave::slave_mode -%>
25 | <% } -%>
26 | <% if $jenkins::slave::executors { -%>
27 | -executors
28 | <%= $jenkins::slave::executors -%>
29 | <% } -%>
30 | <% if $jenkins::slave::quoted_ui_user { -%>
31 | -username
32 | <%= $jenkins::slave::quoted_ui_user -%>
33 | <% } -%>
34 | <% if $jenkins::slave::quoted_ui_pass { -%>
35 | -passwordEnvVariable
36 | JENKINS_PASSWORD
37 | <% } -%>
38 | <% if $jenkins::slave::slave_name { -%>
39 | -name
40 | <%= $jenkins::slave::slave_name -%>
41 | <% } -%>
42 | <% if $jenkins::slave::masterurl { -%>
43 | -master
44 | <%= $jenkins::slave::masterurl -%>
45 | <% } -%>
46 | <% if $jenkins::slave::slave_home { -%>
47 | -fsroot
48 | <%= $jenkins::slave::slave_home -%>
49 | <% } -%>
50 | <% if $jenkins::slave::disable_clients_unique_id { -%>
51 | -disableClientsUniqueId
52 | <% } -%>
53 | <% if $jenkins::slave::disable_ssl_verification { -%>
54 | -disableSslVerification
55 | <% } -%>
56 | <% if $jenkins::slave::delete_existing_clients { -%>
57 | -deleteExistingClients
58 | <% } -%>
59 | <% if $jenkins::slave::description { -%>
60 | -description
61 | <%= $jenkins::slave::description -%>
62 | <% } -%>
63 | <% if $jenkins::slave::autodiscoveryaddress { -%>
64 | -autoDiscoveryAddress
65 | <%= $jenkins::slave::autodiscoveryaddress -%>
66 | <% } -%>
67 | <% if $jenkins::slave::_real_tool_locations { -%>
68 | <% $jenkins::slave::_real_tool_locations.each |$location| { -%>
69 | -toolLocation
70 | <%= $location -%>
71 | <% } -%>
72 | <% } -%>
73 | <% unless empty($jenkins::slave::swarm_client_args) { -%>
74 | <%= join($jenkins::slave::swarm_client_args, ' ') -%>
75 | <% } -%>
76 |
77 | KeepAlive
78 |
79 | RunAtLoad
80 |
81 | UserName
82 | <%= $jenkins::slave::slave_user %>
83 | WorkingDirectory
84 | <%= $jenkins::slave::slave_home %>
85 | SessionCreate
86 |
87 | StandardInPath
88 | /dev/null
89 | StandardErrorPath
90 | /var/log/jenkins/org.jenkins-ci.slave.jnlp.log
91 | StandardOutPath
92 | /var/log/jenkins/org.jenkins-ci.slave.jnlp.log
93 |
94 |
95 |
--------------------------------------------------------------------------------
/templates/proxy.xml.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= @proxy_host %>
3 | <%= @proxy_port %>
4 | <% if @no_proxy_list -%>
5 | <%= @no_proxy_list.join("\n") %>
6 | <% end -%>
7 |
8 |
--------------------------------------------------------------------------------
/types/tunnel.pp:
--------------------------------------------------------------------------------
1 | # A custom data type for a jenkins tunnel verification
2 | type Jenkins::Tunnel = Variant[Pattern[/.+:$/],Pattern[/.+:[0-9]+/], Pattern[/^:[0-9]+/]]
3 |
--------------------------------------------------------------------------------