├── .devcontainer ├── Dockerfile ├── README.md └── devcontainer.json ├── .fixtures.yml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.MD ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── mend.yml │ ├── nightly.yml │ ├── release.yml │ └── release_prep.yml ├── .gitignore ├── .gitpod.Dockerfile ├── .gitpod.yml ├── .pdkignore ├── .puppet-lint.rc ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .sync.yml ├── .vscode └── extensions.json ├── .yardopts ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── Gemfile ├── HISTORY.md ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── data └── common.yaml ├── functions └── sanitised_name.pp ├── hiera.yaml ├── lib ├── facter │ └── docker.rb └── puppet │ ├── functions │ ├── docker │ │ └── env.rb │ └── docker_params_changed.rb │ ├── parser │ └── functions │ │ ├── docker_exec_flags.rb │ │ ├── docker_plugin_enable_flags.rb │ │ ├── docker_plugin_install_flags.rb │ │ ├── docker_plugin_remove_flags.rb │ │ ├── docker_run_flags.rb │ │ ├── docker_secrets_flags.rb │ │ ├── docker_service_flags.rb │ │ ├── docker_stack_flags.rb │ │ ├── docker_swarm_init_flags.rb │ │ └── docker_swarm_join_flags.rb │ ├── provider │ ├── docker_compose │ │ └── ruby.rb │ ├── docker_network │ │ └── ruby.rb │ ├── docker_stack │ │ └── ruby.rb │ └── docker_volume │ │ └── ruby.rb │ └── type │ ├── docker_compose.rb │ ├── docker_network.rb │ ├── docker_stack.rb │ └── docker_volume.rb ├── manifests ├── compose.pp ├── config.pp ├── exec.pp ├── image.pp ├── images.pp ├── init.pp ├── install.pp ├── machine.pp ├── networks.pp ├── params.pp ├── plugin.pp ├── plugins.pp ├── registry.pp ├── registry_auth.pp ├── repos.pp ├── run.pp ├── run_instance.pp ├── secrets.pp ├── service.pp ├── services.pp ├── stack.pp ├── swarm.pp ├── swarms.pp ├── system_user.pp ├── systemd_reload.pp ├── volumes.pp └── windows_account.pp ├── metadata.json ├── pdk.yaml ├── provision.yaml ├── spec ├── acceptance │ ├── compose_v3_spec.rb │ ├── docker_custom_source_spec.rb │ ├── docker_full_spec.rb │ ├── docker_params_changed_spec.rb │ ├── docker_spec.rb │ ├── machine_spec.rb │ ├── network_spec.rb │ ├── plugin_spec.rb │ ├── stack_spec.rb │ └── volume_spec.rb ├── acceptance_swarm │ ├── default.yml │ ├── nodesets │ │ └── pooler │ │ │ ├── ubuntu-1604.yml │ │ │ └── win-2016.yml │ └── swarm_spec.rb ├── classes │ ├── compose_spec.rb │ ├── images_spec.rb │ ├── init_spec.rb │ ├── machine_spec.rb │ ├── networks_spec.rb │ └── plugins_spec.rb ├── default_facts.yml ├── defines │ ├── exec_spec.rb │ ├── image_spec.rb │ ├── plugin_spec.rb │ ├── registry_spec.rb │ ├── run_spec.rb │ ├── secrets_spec.rb │ ├── services_spec.rb │ ├── stack_spec.rb │ └── swarm_spec.rb ├── fixtures │ └── facts │ │ ├── docker_info │ │ ├── docker_info_swarm_inactive │ │ ├── docker_network_inspect_bridge │ │ ├── docker_network_inspect_dummyapp_default │ │ ├── docker_network_inspect_host │ │ ├── docker_network_inspect_none │ │ ├── docker_network_list │ │ ├── docker_swarm_manager_token │ │ ├── docker_swarm_worker_token │ │ ├── docker_version │ │ ├── facts_with_compose │ │ ├── facts_without_compose │ │ └── processors ├── functions │ └── env_spec.rb ├── helper │ ├── get_defaults.rb │ ├── get_docker_exec_flags.rb │ ├── get_docker_params_changed.rb │ ├── get_docker_plugin_enable_flags.rb │ ├── get_docker_plugin_install_flags.rb │ ├── get_docker_plugin_remove_flags.rb │ ├── get_docker_run_flags.rb │ ├── get_docker_secrets_flags.rb │ ├── get_docker_service_flags.rb │ ├── get_docker_stack_flags.rb │ ├── get_docker_swarm_init_flags.rb │ ├── get_docker_swarm_join_flags.rb │ ├── get_values_init.rb │ ├── pw_hash.rb │ └── windows_facts.rb ├── shared_examples.rb ├── shared_examples │ ├── compose.rb │ ├── config.rb │ ├── exec.rb │ ├── image.rb │ ├── install.rb │ ├── machine.rb │ ├── params.rb │ ├── plugin.rb │ ├── registry.rb │ ├── repos.rb │ ├── run.rb │ ├── secrets.rb │ ├── service.rb │ ├── services.rb │ ├── stack.rb │ ├── swarm.rb │ └── system_user.rb ├── spec_helper.rb ├── spec_helper_acceptance.rb ├── spec_helper_acceptance_local.rb └── unit │ └── lib │ ├── facter │ └── docker_spec.rb │ └── puppet │ ├── parser │ └── functions │ │ └── docker_run_flags_spec.rb │ ├── provider │ └── docker_network_spec.rb │ └── type │ ├── docker_compose_spec.rb │ ├── docker_network_spec.rb │ ├── docker_stack_spec.rb │ └── docker_volume_spec.rb ├── tasks ├── node_ls.json ├── node_ls.rb ├── node_rm.json ├── node_rm.rb ├── node_update.json ├── node_update.rb ├── service_create.json ├── service_create.rb ├── service_rm.json ├── service_rm.rb ├── service_scale.json ├── service_scale.rb ├── service_update.json ├── service_update.rb ├── swarm_init.json ├── swarm_init.rb ├── swarm_join.json ├── swarm_join.rb ├── swarm_leave.json ├── swarm_leave.rb ├── swarm_token.json ├── swarm_token.rb ├── swarm_update.json └── swarm_update.rb └── templates ├── docker-run-start.epp ├── docker-run-stop.epp ├── etc ├── conf.d │ ├── docker.epp │ └── docker.gentoo.epp ├── default │ └── docker.epp ├── init.d │ └── docker-run.epp ├── sysconfig │ ├── docker-storage-setup.epp │ ├── docker-storage.epp │ ├── docker.epp │ └── docker.systemd.epp └── systemd │ └── system │ ├── docker-run.epp │ ├── docker.service.d │ ├── service-overrides-debian.conf.epp │ └── service-overrides-rhel.conf.epp │ └── docker.socket.d │ └── socket-overrides.conf.epp ├── update_docker_image.sh.epp ├── usr └── local │ └── bin │ └── docker-run.sh.epp └── windows ├── check_docker.ps1.epp ├── check_docker_url.ps1.epp ├── check_hash.ps1.epp ├── check_powershell_provider.ps1.epp ├── compute_hash.ps1.epp ├── config └── daemon.json.epp ├── download_docker.ps1.epp ├── download_docker_compose.ps1.epp ├── download_docker_machine.ps1.epp ├── install_powershell_provider.ps1.epp ├── remove_docker.ps1.epp └── update_docker_image.ps1.epp /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM puppet/pdk:latest 2 | 3 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 4 | && apt-get -y install --no-install-recommends build-essential 5 | 6 | # [Optional] Uncomment this section to install additional packages. 7 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 8 | # && apt-get -y install --no-install-recommends 9 | -------------------------------------------------------------------------------- /.devcontainer/README.md: -------------------------------------------------------------------------------- 1 | # devcontainer 2 | 3 | 4 | For format details, see https://aka.ms/devcontainer.json. 5 | 6 | For config options, see the README at: 7 | https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet 8 | 9 | ``` json 10 | { 11 | "name": "Puppet Development Kit (Community)", 12 | "dockerFile": "Dockerfile", 13 | 14 | // Set *default* container specific settings.json values on container create. 15 | "settings": { 16 | "terminal.integrated.profiles.linux": { 17 | "bash": { 18 | "path": "bash", 19 | } 20 | } 21 | }, 22 | 23 | // Add the IDs of extensions you want installed when the container is created. 24 | "extensions": [ 25 | "puppet.puppet-vscode", 26 | "rebornix.Ruby" 27 | ], 28 | 29 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 30 | "forwardPorts": [], 31 | 32 | // Use 'postCreateCommand' to run commands after the container is created. 33 | "postCreateCommand": "pdk --version", 34 | } 35 | ``` 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Puppet Development Kit (Community)", 3 | "dockerFile": "Dockerfile", 4 | 5 | "settings": { 6 | "terminal.integrated.profiles.linux": { 7 | "bash": { 8 | "path": "bash" 9 | } 10 | } 11 | }, 12 | 13 | "extensions": [ 14 | "puppet.puppet-vscode", 15 | "rebornix.Ruby" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | forge_modules: 3 | stdlib: 'puppetlabs-stdlib' 4 | apt: 'puppetlabs-apt' 5 | powershell: 'puppetlabs-powershell' 6 | reboot: 'puppetlabs-reboot' 7 | repositories: 8 | facts: 'https://github.com/puppetlabs/puppetlabs-facts.git' 9 | puppet_agent: 10 | repo: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' 11 | ref: v4.13.0 12 | provision: 'https://github.com/puppetlabs/provision.git' 13 | yumrepo_core: 14 | repo: https://github.com/puppetlabs/puppetlabs-yumrepo_core.git 15 | puppet_version: ">= 6.0.0" 16 | symlinks: 17 | docker: "#{source_dir}" 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.rb eol=lf 2 | *.erb eol=lf 3 | *.pp eol=lf 4 | *.sh eol=lf 5 | *.epp eol=lf 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.MD: -------------------------------------------------------------------------------- 1 | 16 | 17 | ## What you expected to happen? 18 | 19 | ## What happened? 20 | 21 | 22 | ## How to reproduce it? 23 | 24 | 25 | ## Anything else we need to know? 26 | 27 | 28 | ## Versions: 29 | 30 | ``` 31 | $ puppet --version 32 | 33 | $ docker version 34 | 35 | $ facter os 36 | 37 | $ puppet module list 38 | ``` 39 | 40 | ## Logs: 41 | ``` 42 | Paste any relevant logs from a puppet run 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | Provide a detailed description of all the changes present in this pull request. 3 | 4 | ## Additional Context 5 | Add any additional context about the problem here. 6 | - [ ] Root cause and the steps to reproduce. (If applicable) 7 | - [ ] Thought process behind the implementation. 8 | 9 | ## Related Issues (if any) 10 | Mention any related issues or pull requests. 11 | 12 | ## Checklist 13 | - [ ] 🟢 Spec tests. 14 | - [ ] 🟢 Acceptance tests. 15 | - [ ] Manually verified. (For example `puppet apply`) -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "ci" 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "main" 7 | workflow_dispatch: 8 | 9 | jobs: 10 | Spec: 11 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_ci.yml@main" 12 | with: 13 | runs_on: "ubuntu-24.04" 14 | secrets: "inherit" 15 | 16 | Acceptance: 17 | needs: Spec 18 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_acceptance.yml@main" 19 | with: 20 | flags: '--provision-service' 21 | secrets: "inherit" 22 | -------------------------------------------------------------------------------- /.github/workflows/mend.yml: -------------------------------------------------------------------------------- 1 | name: "mend" 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "main" 7 | schedule: 8 | - cron: "0 0 * * *" 9 | workflow_dispatch: 10 | 11 | jobs: 12 | 13 | mend: 14 | uses: "puppetlabs/cat-github-actions/.github/workflows/mend_ruby.yml@main" 15 | secrets: "inherit" 16 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: "nightly" 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | Spec: 10 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_ci.yml@main" 11 | with: 12 | runs_on: "ubuntu-24.04" 13 | secrets: "inherit" 14 | 15 | Acceptance: 16 | needs: Spec 17 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_acceptance.yml@main" 18 | with: 19 | flags: '--provision-service' 20 | secrets: "inherit" 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Publish module" 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | release: 8 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_release.yml@main" 9 | secrets: "inherit" 10 | -------------------------------------------------------------------------------- /.github/workflows/release_prep.yml: -------------------------------------------------------------------------------- 1 | name: "Release Prep" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: "Module version to be released. Must be a valid semver string. (1.2.3)" 8 | required: true 9 | 10 | jobs: 11 | release_prep: 12 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_release_prep.yml@main" 13 | with: 14 | version: "${{ github.event.inputs.version }}" 15 | secrets: "inherit" 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .*.sw[op] 3 | .metadata 4 | .yardoc 5 | .yardwarns 6 | *.iml 7 | /.bundle/ 8 | /.idea/ 9 | /.vagrant/ 10 | /coverage/ 11 | /bin/ 12 | /doc/ 13 | /Gemfile.local 14 | /Gemfile.lock 15 | /junit/ 16 | /log/ 17 | /pkg/ 18 | /spec/fixtures/manifests/ 19 | /spec/fixtures/modules/* 20 | /tmp/ 21 | /vendor/ 22 | /convert_report.txt 23 | /update_report.txt 24 | .DS_Store 25 | .project 26 | .envrc 27 | /inventory.yaml 28 | /spec/fixtures/litmus_inventory.yaml 29 | -------------------------------------------------------------------------------- /.gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | RUN sudo wget https://apt.puppet.com/puppet-tools-release-bionic.deb && \ 3 | wget https://apt.puppetlabs.com/puppet6-release-bionic.deb && \ 4 | sudo dpkg -i puppet6-release-bionic.deb && \ 5 | sudo dpkg -i puppet-tools-release-bionic.deb && \ 6 | sudo apt-get update && \ 7 | sudo apt-get install -y pdk zsh puppet-agent && \ 8 | sudo apt-get clean && \ 9 | sudo rm -rf /var/lib/apt/lists/* 10 | RUN sudo usermod -s $(which zsh) gitpod && \ 11 | sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" && \ 12 | echo "plugins=(git gitignore github gem pip bundler python ruby docker docker-compose)" >> /home/gitpod/.zshrc && \ 13 | echo 'PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/puppetlabs/bin:/opt/puppetlabs/puppet/bin"' >> /home/gitpod/.zshrc && \ 14 | sudo /opt/puppetlabs/puppet/bin/gem install puppet-debugger hub -N && \ 15 | mkdir -p /home/gitpod/.config/puppet && \ 16 | /opt/puppetlabs/puppet/bin/ruby -r yaml -e "puts ({'disabled' => true}).to_yaml" > /home/gitpod/.config/puppet/analytics.yml 17 | RUN rm -f puppet6-release-bionic.deb puppet-tools-release-bionic.deb 18 | ENTRYPOINT /usr/bin/zsh 19 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: .gitpod.Dockerfile 3 | 4 | tasks: 5 | - init: pdk bundle install 6 | 7 | vscode: 8 | extensions: 9 | - puppet.puppet-vscode@1.2.0:f5iEPbmOj6FoFTOV6q8LTg== 10 | -------------------------------------------------------------------------------- /.pdkignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .*.sw[op] 3 | .metadata 4 | .yardoc 5 | .yardwarns 6 | *.iml 7 | /.bundle/ 8 | /.idea/ 9 | /.vagrant/ 10 | /coverage/ 11 | /bin/ 12 | /doc/ 13 | /Gemfile.local 14 | /Gemfile.lock 15 | /junit/ 16 | /log/ 17 | /pkg/ 18 | /spec/fixtures/manifests/ 19 | /spec/fixtures/modules/* 20 | /tmp/ 21 | /vendor/ 22 | /convert_report.txt 23 | /update_report.txt 24 | .DS_Store 25 | .project 26 | .envrc 27 | /inventory.yaml 28 | /spec/fixtures/litmus_inventory.yaml 29 | /.fixtures.yml 30 | /Gemfile 31 | /.gitattributes 32 | /.github/ 33 | /.gitignore 34 | /.pdkignore 35 | /.puppet-lint.rc 36 | /Rakefile 37 | /rakelib/ 38 | /.rspec 39 | /..yml 40 | /.yardopts 41 | /spec/ 42 | /.vscode/ 43 | /.sync.yml 44 | /.devcontainer/ 45 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | --relative 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2023-11-28 17:27:51 UTC using RuboCop version 1.48.1. 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: 2 10 | # This cop supports safe autocorrection (--autocorrect). 11 | Lint/RedundantCopDisableDirective: 12 | Exclude: 13 | - 'spec/spec_helper.rb' 14 | - 'spec/spec_helper_acceptance_local.rb' 15 | 16 | # Offense count: 22 17 | # Configuration parameters: AllowKeywordBlockArguments. 18 | Lint/UnderscorePrefixedVariableName: 19 | Exclude: 20 | - 'spec/helper/get_defaults.rb' 21 | - 'spec/helper/get_values_init.rb' 22 | - 'spec/shared_examples/compose.rb' 23 | - 'spec/shared_examples/config.rb' 24 | - 'spec/shared_examples/exec.rb' 25 | - 'spec/shared_examples/image.rb' 26 | - 'spec/shared_examples/install.rb' 27 | - 'spec/shared_examples/machine.rb' 28 | - 'spec/shared_examples/params.rb' 29 | - 'spec/shared_examples/plugin.rb' 30 | - 'spec/shared_examples/registry.rb' 31 | 32 | # Offense count: 7 33 | Lint/UselessAssignment: 34 | Exclude: 35 | - 'spec/classes/networks_spec.rb' 36 | - 'spec/defines/run_spec.rb' 37 | - 'spec/helper/get_defaults.rb' 38 | - 'spec/shared_examples/compose.rb' 39 | - 'spec/shared_examples/image.rb' 40 | - 'spec/shared_examples/machine.rb' 41 | 42 | # Offense count: 23 43 | # Configuration parameters: EnforcedStyle, IgnoreSharedExamples. 44 | # SupportedStyles: always, named_only 45 | RSpec/NamedSubject: 46 | Exclude: 47 | - 'spec/classes/compose_spec.rb' 48 | - 'spec/classes/images_spec.rb' 49 | - 'spec/classes/init_spec.rb' 50 | - 'spec/classes/networks_spec.rb' 51 | - 'spec/classes/plugins_spec.rb' 52 | - 'spec/defines/image_spec.rb' 53 | - 'spec/defines/plugin_spec.rb' 54 | - 'spec/defines/run_spec.rb' 55 | - 'spec/defines/services_spec.rb' 56 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ".gitlab-ci.yml": 3 | delete: true 4 | ".rubocop.yml": 5 | include_todos: true 6 | appveyor.yml: 7 | delete: true 8 | 9 | Gemfile: 10 | optional: 11 | ":development": 12 | - gem: ruby-pwsh 13 | - gem: mocha 14 | version: '< 1.2.0' 15 | ":system_tests": 16 | - gem: rspec-retry 17 | Rakefile: 18 | changelog_since_tag: 3.5.0 19 | spec/spec_helper.rb: 20 | unmanaged: true 21 | coverage_report: true 22 | .gitpod.Dockerfile: 23 | unmanaged: false 24 | .gitpod.yml: 25 | unmanaged: false 26 | .github/workflows/auto_release.yml: 27 | unmanaged: false 28 | .github/workflows/ci.yml: 29 | unmanaged: true 30 | .github/workflows/nightly.yml: 31 | unmanaged: true 32 | .github/workflows/release.yml: 33 | unmanaged: false 34 | .travis.yml: 35 | delete: true 36 | .devcontainer/Dockerfile: 37 | unmanaged: true 38 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "puppet.puppet-vscode", 4 | "rebornix.Ruby" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --markup markdown 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Setting ownership to the modules team 2 | * @puppetlabs/modules 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Puppet modules 2 | 3 | Check out our [Contributing to Supported Modules Blog Post](https://puppetlabs.github.io/iac/docs/contributing_to_a_module.html) to find all the information that you will need. 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler' 4 | require 'puppet_litmus/rake_tasks' if Gem.loaded_specs.key? 'puppet_litmus' 5 | require 'puppetlabs_spec_helper/rake_tasks' 6 | require 'puppet-syntax/tasks/puppet-syntax' 7 | require 'puppet-strings/tasks' if Gem.loaded_specs.key? 'puppet-strings' 8 | 9 | PuppetLint.configuration.send('disable_relative') 10 | -------------------------------------------------------------------------------- /data/common.yaml: -------------------------------------------------------------------------------- 1 | --- {} 2 | -------------------------------------------------------------------------------- /functions/sanitised_name.pp: -------------------------------------------------------------------------------- 1 | # == Function: docker::sanitised_name 2 | # 3 | # Function to sanitise container name. 4 | # 5 | # === Parameters 6 | # 7 | # [*name*] 8 | # Name to sanitise 9 | # 10 | function docker::sanitised_name($name) { 11 | regsubst($name, '[^0-9A-Za-z.\-_]', '-', 'G') 12 | } 13 | -------------------------------------------------------------------------------- /hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 5 3 | 4 | defaults: # Used for any hierarchy level that omits these keys. 5 | datadir: data # This path is relative to hiera.yaml's directory. 6 | data_hash: yaml_data # Use the built-in YAML backend. 7 | 8 | hierarchy: 9 | - name: "osfamily/major release" 10 | paths: 11 | # Used to distinguish between Debian and Ubuntu 12 | - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" 13 | - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" 14 | # Used for Solaris 15 | - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" 16 | - name: "osfamily" 17 | paths: 18 | - "os/%{facts.os.name}.yaml" 19 | - "os/%{facts.os.family}.yaml" 20 | - name: 'common' 21 | path: 'common.yaml' 22 | -------------------------------------------------------------------------------- /lib/puppet/functions/docker/env.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Functions.create_function(:'docker::env') do 4 | dispatch :env do 5 | param 'Array', :args 6 | return_type 'Array' 7 | end 8 | 9 | def env(args) 10 | args 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_exec_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_exec_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker exec flags 9 | newfunction(:docker_exec_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | 13 | flags << '--detach=true' if opts['detach'] 14 | 15 | flags << '--interactive=true' if opts['interactive'] 16 | 17 | flags << '--tty=true' if opts['tty'] 18 | 19 | opts['env']&.each do |namevaluepair| 20 | flags << "--env #{namevaluepair}" 21 | end 22 | 23 | flags.flatten.join(' ') 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_plugin_enable_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_plugin_remove_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker plugin remove flags 9 | newfunction(:docker_plugin_enable_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | flags << '--force' if opts['force_remove'] == true 13 | if opts['plugin_alias'] && opts['plugin_alias'].to_s != 'undef' 14 | flags << "'#{opts['plugin_alias']}'" 15 | elsif opts['plugin_name'] && opts['plugin_name'].to_s != 'undef' 16 | flags << "'#{opts['plugin_name']}'" 17 | end 18 | flags.flatten.join(' ') 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_plugin_install_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_plugin_install_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker plugin install flags 9 | newfunction(:docker_plugin_install_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | flags << "--alias #{opts['plugin_alias']}" if opts['plugin_alias'] && opts['plugin_alias'].to_s != 'undef' 13 | flags << '--disable' if opts['disable_on_install'] == true 14 | flags << '--disable-content-trust' if opts['disable_content_trust'] == true 15 | flags << '--grant-all-permissions' if opts['grant_all_permissions'] == true 16 | flags << "'#{opts['plugin_name']}'" if opts['plugin_name'] && opts['plugin_name'].to_s != 'undef' 17 | if opts['settings'].is_a? Array 18 | opts['settings'].each do |setting| 19 | flags << setting.to_s 20 | end 21 | end 22 | flags.flatten.join(' ') 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_plugin_remove_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_plugin_remove_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker plugin remove flags 9 | newfunction(:docker_plugin_remove_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | flags << '--force' if opts['force_remove'] == true 13 | flags << "'#{opts['plugin_name']}'" if opts['plugin_name'] && opts['plugin_name'].to_s != 'undef' 14 | flags.flatten.join(' ') 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_run_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # docker_run_flags.rb 5 | # 6 | module Puppet::Parser::Functions 7 | newfunction(:'docker::escape', type: :rvalue) do |args| 8 | subject = args[0] 9 | 10 | escape_function = if self['facts'] && self['facts']['os']['family'] == 'windows' 11 | 'stdlib::powershell_escape' 12 | else 13 | 'stdlib::shell_escape' 14 | end 15 | 16 | call_function(escape_function, subject) 17 | end 18 | 19 | # Transforms a hash into a string of docker flags 20 | newfunction(:docker_run_flags, type: :rvalue) do |args| 21 | opts = args[0] || {} 22 | flags = [] 23 | 24 | flags << "-u #{call_function('docker::escape', [opts['username']])}" if opts['username'] 25 | 26 | flags << "-h #{call_function('docker::escape', [opts['hostname']])}" if opts['hostname'] 27 | 28 | flags << "--restart '#{opts['restart']}'" if opts['restart'] 29 | 30 | if opts['net'] 31 | if opts['net'].is_a? String 32 | flags << "--net #{call_function('docker::escape', [opts['net']])}" 33 | elsif opts['net'].is_a? Array 34 | flags += opts['net'].map { |item| ["--net #{call_function('docker::escape', [item])}"] } 35 | end 36 | end 37 | 38 | flags << "-m #{opts['memory_limit']}" if opts['memory_limit'] 39 | 40 | cpusets = [opts['cpuset']].flatten.compact 41 | unless cpusets.empty? 42 | value = cpusets.join(',') 43 | flags << "--cpuset-cpus=#{value}" 44 | end 45 | 46 | flags << '-n false' if opts['disable_network'] 47 | 48 | flags << '--privileged' if opts['privileged'] 49 | 50 | flags << "--health-cmd='#{opts['health_check_cmd']}'" if opts['health_check_cmd'] && opts['health_check_cmd'].to_s != 'undef' 51 | 52 | flags << "--health-interval=#{opts['health_check_interval']}s" if opts['health_check_interval'] && opts['health_check_interval'].to_s != 'undef' 53 | 54 | flags << '-t' if opts['tty'] 55 | 56 | flags << '--read-only=true' if opts['read_only'] 57 | 58 | params_join_char = if opts['osfamily'] && opts['osfamily'].to_s != 'undef' 59 | opts['osfamily'].casecmp('windows').zero? ? " `\n" : " \\\n" 60 | else 61 | " \\\n" 62 | end 63 | 64 | multi_flags = ->(values, fmt) { 65 | filtered = [values].flatten.compact 66 | filtered.map { |val| (fmt + params_join_char) % call_function('docker::escape', [val]) } 67 | } 68 | 69 | [ 70 | ['--dns %s', 'dns'], 71 | ['--dns-search %s', 'dns_search'], 72 | ['--expose=%s', 'expose'], 73 | ['--link %s', 'links'], 74 | ['--lxc-conf=%s', 'lxc_conf'], 75 | ['--volumes-from %s', 'volumes_from'], 76 | ['-e %s', 'env'], 77 | ['--env-file %s', 'env_file'], 78 | ['-p %s', 'ports'], 79 | ['-l %s', 'labels'], 80 | ['--add-host %s', 'hostentries'], 81 | ['-v %s', 'volumes'], 82 | ].each do |(format, key)| 83 | values = opts[key] 84 | new_flags = multi_flags.call(values, format) 85 | flags.concat(new_flags) 86 | end 87 | 88 | opts['extra_params'].each do |param| 89 | flags << param 90 | end 91 | 92 | # Some software (inc systemd) will truncate very long lines using glibc's 93 | # max line length. Wrap options across multiple lines with '\' to avoid 94 | flags.flatten.join(params_join_char) 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_secrets_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_secrets_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker swarm init flags 9 | newfunction(:docker_secrets_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | 13 | flags << 'create' if opts['ensure'].to_s == 'present' 14 | 15 | flags << "'#{opts['secret_name']}'" if opts['secret_name'] && opts['secret_name'].to_s != 'undef' 16 | 17 | flags << "'#{opts['secret_path']}'" if opts['secret_path'] && opts['secret_path'].to_s != 'undef' 18 | 19 | multi_flags = ->(values, format) { 20 | filtered = [values].flatten.compact 21 | filtered.map { |val| format + (" \\\n" % val) } 22 | } 23 | [ 24 | ['-l %s', 'label'], 25 | ].each do |(format, key)| 26 | values = opts[key] 27 | new_flags = multi_flags.call(values, format) 28 | flags.concat(new_flags) 29 | end 30 | 31 | flags.flatten.join(' ') 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_service_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_service_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker swarm init flags 9 | newfunction(:docker_service_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | 13 | flags << "'#{opts['service_name']}'" if opts['service_name'] && opts['service_name'].to_s != 'undef' 14 | 15 | flags << '--detach' if opts['detach'].to_s != 'false' 16 | 17 | if opts['env'].is_a? Array 18 | opts['env'].each do |env| 19 | flags << "--env '#{env}'" 20 | end 21 | end 22 | 23 | if opts['label'].is_a? Array 24 | opts['label'].each do |label| 25 | flags << "--label #{label}" 26 | end 27 | end 28 | 29 | if opts['mounts'].is_a? Array 30 | opts['mounts'].each do |mount| 31 | flags << "--mount #{mount}" 32 | end 33 | end 34 | 35 | if opts['networks'].is_a? Array 36 | opts['networks'].each do |network| 37 | flags << "--network #{network}" 38 | end 39 | end 40 | 41 | if opts['publish'].is_a? Array 42 | opts['publish'].each do |port| 43 | flags << "--publish #{port}" 44 | end 45 | elsif opts['publish'] && opts['publish'].to_s != 'undef' 46 | flags << "--publish '#{opts['publish']}'" 47 | end 48 | 49 | flags << "--replicas '#{opts['replicas']}'" if opts['replicas'] && opts['replicas'].to_s != 'undef' 50 | 51 | flags << '--tty' if opts['tty'].to_s != 'false' 52 | 53 | flags << "--user '#{opts['user']}'" if opts['user'] && opts['user'].to_s != 'undef' 54 | 55 | flags << "--workdir '#{opts['workdir']}'" if opts['workdir'] && opts['workdir'].to_s != 'undef' 56 | 57 | if opts['extra_params'].is_a? Array 58 | opts['extra_params'].each do |param| 59 | flags << param 60 | end 61 | end 62 | 63 | flags << "-H '#{opts['host_socket']}'" if opts['host_socket'] && opts['host_socket'].to_s != 'undef' 64 | 65 | if opts['registry_mirror'].is_a? Array 66 | opts['registry_mirror'].each do |param| 67 | flags << "--registry-mirror='#{param}'" 68 | end 69 | elsif opts['registry_mirror'] && opts['registry_mirror'].to_s != 'undef' 70 | flags << "--registry-mirror='#{opts['registry_mirror']}'" 71 | end 72 | 73 | flags << "'#{opts['image']}'" if opts['image'] && opts['image'].to_s != 'undef' 74 | 75 | if opts['command'].is_a? Array 76 | flags << opts['command'].join(' ') 77 | elsif opts['command'] && opts['command'].to_s != 'undef' 78 | flags << opts['command'].to_s 79 | end 80 | 81 | flags.flatten.join(' ') 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_stack_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_stack_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker stack flags 9 | newfunction(:docker_stack_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | 13 | flags << "--bundle-file '#{opts['bundle_file']}'" if opts['bundle_file'] && opts['bundle_file'].to_s != 'undef' 14 | 15 | if opts['compose_files'] && opts['compose_files'].to_s != 'undef' 16 | opts['compose_files'].each do |file| 17 | flags << "--compose-file '#{file}'" 18 | end 19 | end 20 | 21 | flags << "--resolve-image '#{opts['resolve_image']}'" if opts['resolve_image'] && opts['resolve_image'].to_s != 'undef' 22 | 23 | flags << '--prune' if opts['prune'] && opts['prune'].to_s != 'undef' 24 | 25 | flags << '--with-registry-auth' if opts['with_registry_auth'] && opts['with_registry_auth'].to_s != 'undef' 26 | 27 | flags.flatten.join(' ') 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_swarm_init_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_swarm_init_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker swarm init flags 9 | newfunction(:docker_swarm_init_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | 13 | flags << 'init' if opts['init'].to_s != 'false' 14 | 15 | flags << "--advertise-addr '#{opts['advertise_addr']}'" if opts['advertise_addr'] && opts['advertise_addr'].to_s != 'undef' 16 | 17 | flags << '--autolock' if opts['autolock'].to_s != 'false' 18 | 19 | flags << "--cert-expiry '#{opts['cert_expiry']}'" if opts['cert_expiry'] && opts['cert_expiry'].to_s != 'undef' 20 | 21 | if opts['default_addr_pool'].is_a? Array 22 | opts['default_addr_pool'].each do |default_addr_pool| 23 | flags << "--default-addr-pool #{default_addr_pool}" 24 | end 25 | end 26 | 27 | flags << "--default-addr-pool-mask-length '#{opts['default_addr_pool_mask_length']}'" if opts['default_addr_pool_mask_length'] && opts['default_addr_pool_mask_length'].to_s != 'undef' 28 | 29 | flags << "--dispatcher-heartbeat '#{opts['dispatcher_heartbeat']}'" if opts['dispatcher_heartbeat'] && opts['dispatcher_heartbeat'].to_s != 'undef' 30 | 31 | flags << "--external-ca '#{opts['external_ca']}'" if opts['external_ca'] && opts['external_ca'].to_s != 'undef' 32 | 33 | flags << '--force-new-cluster' if opts['force_new_cluster'].to_s != 'false' 34 | 35 | flags << "--listen-addr '#{opts['listen_addr']}'" if opts['listen_addr'] && opts['listen_addr'].to_s != 'undef' 36 | 37 | flags << "--max-snapshots '#{opts['max_snapshots']}'" if opts['max_snapshots'] && opts['max_snapshots'].to_s != 'undef' 38 | 39 | flags << "--snapshot-interval '#{opts['snapshot_interval']}'" if opts['snapshot_interval'] && opts['snapshot_interval'].to_s != 'undef' 40 | 41 | flags.flatten.join(' ') 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/docker_swarm_join_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | # 5 | # docker_swarm_join_flags.rb 6 | # 7 | module Puppet::Parser::Functions 8 | # Transforms a hash into a string of docker swarm init flags 9 | newfunction(:docker_swarm_join_flags, type: :rvalue) do |args| 10 | opts = args[0] || {} 11 | flags = [] 12 | 13 | flags << 'join' if opts['join'].to_s != 'false' 14 | 15 | flags << "--advertise-addr '#{opts['advertise_addr']}'" if opts['advertise_addr'] && opts['advertise_addr'].to_s != 'undef' 16 | 17 | flags << "--listen-addr \"#{opts['listen_addr']}\"" if opts['listen_addr'] && opts['listen_addr'].to_s != 'undef' 18 | 19 | flags << "--token '#{opts['token']}'" if opts['token'] && opts['token'].to_s != 'undef' 20 | 21 | flags.flatten.join(' ') 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/puppet/provider/docker_network/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | 5 | Puppet::Type.type(:docker_network).provide(:ruby) do 6 | desc 'Support for Docker Networking' 7 | 8 | mk_resource_methods 9 | 10 | has_command(:docker, 'docker') 11 | 12 | def network_conf 13 | flags = ['network', 'create'] 14 | multi_flags = ->(values, format) { 15 | filtered = [values].flatten.compact 16 | filtered.map { |val| format % val } 17 | } 18 | 19 | [ 20 | ['--driver=%s', :driver], 21 | ['--subnet=%s', :subnet], 22 | ['--gateway=%s', :gateway], 23 | ['--ip-range=%s', :ip_range], 24 | ['--ipam-driver=%s', :ipam_driver], 25 | ['--aux-address=%s', :aux_address], 26 | ['--opt=%s', :options], 27 | ].each do |(format, key)| 28 | values = resource[key] 29 | new_flags = multi_flags.call(values, format) 30 | flags.concat(new_flags) 31 | end 32 | 33 | if defined?(resource[:additional_flags]) 34 | additional_flags = [] 35 | if resource[:additional_flags].is_a?(String) 36 | additional_flags = resource[:additional_flags].split 37 | elsif resource[:additional_flags].is_a?(Array) 38 | additional_flags = resource[:additional_flags] 39 | end 40 | additional_flags.each do |additional_flag| 41 | flags << additional_flag 42 | end 43 | end 44 | 45 | flags << resource[:name] 46 | end 47 | 48 | def self.instances 49 | output = docker(['network', 'ls']) 50 | lines = output.split("\n") 51 | lines.shift # remove header row 52 | lines.map do |line| 53 | _, name, driver = line.split 54 | inspect = docker(['network', 'inspect', name]) 55 | obj = JSON.parse(inspect).first 56 | ipam_driver = (obj['IPAM']['Driver'] unless obj['IPAM']['Driver'].nil?) 57 | subnet = (obj['IPAM']['Config'].first['Subnet'] if !(obj['IPAM']['Config'].nil? || obj['IPAM']['Config'].empty?) && (obj['IPAM']['Config'].first.key? 'Subnet')) 58 | new( 59 | name: name, 60 | id: obj['Id'], 61 | ipam_driver: ipam_driver, 62 | subnet: subnet, 63 | ensure: :present, 64 | driver: driver, 65 | ) 66 | end 67 | end 68 | 69 | def self.prefetch(resources) 70 | instances.each do |prov| 71 | if resource = resources[prov.name] # rubocop:disable Lint/AssignmentInCondition 72 | resource.provider = prov 73 | end 74 | end 75 | end 76 | 77 | def flush 78 | raise Puppet::Error, _('Docker network does not support mutating existing networks') if !@property_hash.empty? && @property_hash[:ensure] != :absent 79 | end 80 | 81 | def exists? 82 | Puppet.info("Checking if docker network #{name} exists") 83 | @property_hash[:ensure] == :present 84 | end 85 | 86 | def create 87 | Puppet.info("Creating docker network #{name}") 88 | docker(network_conf) 89 | end 90 | 91 | def destroy 92 | Puppet.info("Removing docker network #{name}") 93 | docker(['network', 'rm', name]) 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/puppet/provider/docker_stack/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'deep_merge' 4 | 5 | Puppet::Type.type(:docker_stack).provide(:ruby) do 6 | desc 'Support for Puppet running Docker Stacks' 7 | 8 | mk_resource_methods 9 | 10 | has_command(:docker, 'docker') 11 | 12 | def exists? 13 | Puppet.info("Checking for stack #{name}") 14 | stack_services = {} 15 | stack_containers = [] 16 | resource[:compose_files].each do |file| 17 | compose_file = YAML.safe_load(File.read(file), [], [], true) 18 | # rubocop:disable Style/StringLiterals 19 | containers = docker([ 20 | 'ps', 21 | '--format', 22 | "{{.Label \"com.docker.swarm.service.name\"}}-{{.Image}}", 23 | '--filter', 24 | "label=com.docker.stack.namespace=#{name}", 25 | ]).split("\n").each do |c| 26 | c.slice!("#{name}_") 27 | end 28 | stack_containers.push(*containers) 29 | stack_containers.uniq! 30 | # rubocop:enable Style/StringLiterals 31 | case compose_file['version'] 32 | when %r{^3(\.[0-7])?$} 33 | stack_services.merge!(compose_file['services']) 34 | else 35 | raise(Puppet::Error, "Unsupported docker compose file syntax version \"#{compose_file['version']}\"!") 36 | end 37 | end 38 | 39 | return false if stack_services.count != stack_containers.count 40 | 41 | counts = Hash[*stack_services.each.map { |key, array| 42 | image = array['image'] || get_image(key, stack_services) 43 | image = "#{image}:latest" unless image.include?(':') 44 | Puppet.info("Checking for compose service #{key} #{image}") 45 | ["#{key}-#{image}", stack_containers.count("#{key}-#{image}")] 46 | }.flatten] 47 | # No containers found for the project 48 | if counts.empty? || 49 | # Containers described in the compose file are not running 50 | counts.any? { |_k, v| v.zero? } 51 | false 52 | else 53 | true 54 | end 55 | end 56 | 57 | def get_image(service_name, stack_services) 58 | image = stack_services[service_name]['image'] 59 | unless image 60 | if stack_services[service_name]['extends'] 61 | image = get_image(stack_services[service_name]['extends'], stack_services) 62 | elsif stack_services[service_name]['build'] 63 | image = "#{name}_#{service_name}" 64 | end 65 | end 66 | image 67 | end 68 | 69 | def create 70 | Puppet.info("Running stack #{name}") 71 | args = ['stack', 'deploy', compose_files, name].insert(1, bundle_file).insert(4, resource[:up_args]).compact 72 | docker(args) 73 | end 74 | 75 | def destroy 76 | Puppet.info("Removing docker stack #{name}") 77 | rm_args = ['stack', 'rm', name] 78 | docker(rm_args) 79 | end 80 | 81 | def bundle_file 82 | return resource[:bundle_file].map { |x| ['-c', x] }.flatten unless resource[:bundle_file].nil? 83 | end 84 | 85 | def compose_files 86 | resource[:compose_files].map { |x| ['-c', x] }.flatten 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/puppet/provider/docker_volume/ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | 5 | Puppet::Type.type(:docker_volume).provide(:ruby) do 6 | desc 'Support for Docker Volumes' 7 | 8 | mk_resource_methods 9 | 10 | has_command(:docker, 'docker') 11 | 12 | def volume_conf 13 | flags = ['volume', 'create'] 14 | multi_flags = ->(values, format) { 15 | filtered = [values].flatten.compact 16 | filtered.map { |val| format % val } 17 | } 18 | 19 | [ 20 | ['--driver=%s', :driver], 21 | ['--opt=%s', :options], 22 | ].each do |(format, key)| 23 | values = resource[key] 24 | new_flags = multi_flags.call(values, format) 25 | flags.concat(new_flags) 26 | end 27 | flags << resource[:name] 28 | end 29 | 30 | def self.instances 31 | output = docker(['volume', 'ls']) 32 | lines = output.split("\n") 33 | lines.shift # remove header row 34 | lines.map do |line| 35 | driver, name = line.split 36 | inspect = docker(['volume', 'inspect', name]) 37 | obj = JSON.parse(inspect).first 38 | new( 39 | name: name, 40 | mountpoint: obj['Mountpoint'], 41 | options: obj['Options'], 42 | ensure: :present, 43 | driver: driver, 44 | ) 45 | end 46 | end 47 | 48 | def self.prefetch(resources) 49 | instances.each do |prov| 50 | if (resource = resources[prov.name]) 51 | resource.provider = prov 52 | end 53 | end 54 | end 55 | 56 | def exists? 57 | Puppet.info("Checking if docker volume #{name} exists") 58 | @property_hash[:ensure] == :present 59 | end 60 | 61 | def create 62 | Puppet.info("Creating docker volume #{name}") 63 | docker(volume_conf) 64 | end 65 | 66 | def destroy 67 | Puppet.info("Removing docker volume #{name}") 68 | docker(['volume', 'rm', name]) 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/puppet/type/docker_compose.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:docker_compose) do 4 | @doc = 'A type representing a Docker Compose file' 5 | 6 | ensurable 7 | 8 | def refresh 9 | provider.restart 10 | end 11 | 12 | newparam(:scale) do 13 | desc 'A hash of compose services and number of containers.' 14 | validate do |value| 15 | raise _('scale should be a Hash') unless value.is_a? Hash 16 | raise _('The name of the compose service in scale should be a String') unless value.all? { |k, _v| k.is_a? String } 17 | raise _('The number of containers in scale should be an Integer') unless value.all? { |_k, v| v.is_a? Integer } 18 | end 19 | end 20 | 21 | newparam(:options) do 22 | desc 'Additional options to be passed directly to docker-compose.' 23 | validate do |value| 24 | raise _('options should be an Array') unless value.is_a? Array 25 | end 26 | end 27 | 28 | newparam(:up_args) do 29 | desc 'Arguments to be passed directly to docker-compose up.' 30 | validate do |value| 31 | raise _('up_args should be a String') unless value.is_a? String 32 | end 33 | end 34 | 35 | newparam(:compose_files, array_matching: :all) do 36 | desc 'An array of Docker Compose Files paths.' 37 | validate do |value| 38 | raise _('compose files should be an array') unless value.is_a? Array 39 | end 40 | end 41 | 42 | newparam(:name) do 43 | isnamevar 44 | desc 'The name of the project' 45 | end 46 | 47 | newparam(:tmpdir) do 48 | desc "Override the temporary directory used by docker-compose. 49 | 50 | This property is useful when the /tmp directory has been mounted 51 | with the noexec option. Or is otherwise being prevented It allows the module consumer to redirect 52 | docker-composes temporary files to a known directory. 53 | 54 | The directory passed to this property must exist and be accessible 55 | by the user that is executing the puppet agent. 56 | " 57 | validate do |value| 58 | raise _('tmpdir should be a String') unless value.is_a? String 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/puppet/type/docker_network.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:docker_network) do 4 | @doc = 'Type representing a Docker network' 5 | ensurable 6 | 7 | newparam(:name) do 8 | isnamevar 9 | desc 'The name of the network' 10 | end 11 | 12 | newproperty(:driver) do 13 | desc 'The network driver used by the network' 14 | end 15 | 16 | newparam(:subnet, array_matching: :all) do 17 | desc 'The subnet in CIDR format that represents a network segment' 18 | end 19 | 20 | newparam(:gateway) do 21 | desc 'An ipv4 or ipv6 gateway for the server subnet' 22 | end 23 | 24 | newparam(:ip_range) do 25 | desc 'The range of IP addresses used by the network' 26 | end 27 | 28 | newproperty(:ipam_driver) do 29 | desc 'The IPAM (IP Address Management) driver' 30 | end 31 | 32 | newparam(:aux_address) do 33 | desc 'Auxiliary ipv4 or ipv6 addresses used by the Network driver' 34 | end 35 | 36 | newparam(:options) do 37 | desc 'Additional options for the network driver' 38 | end 39 | 40 | newparam(:additional_flags) do 41 | desc "Additional flags for the 'docker network create'" 42 | end 43 | 44 | newproperty(:id) do 45 | desc 'The ID of the network provided by Docker' 46 | validate do |value| 47 | raise(Puppet::ParseError, "#{value} is read-only and is only available via puppet resource.") 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/puppet/type/docker_stack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:docker_stack) do 4 | @doc = 'A type representing a Docker Stack' 5 | 6 | ensurable 7 | 8 | newparam(:bundle_file) do 9 | desc 'Path to a Distributed Application Bundle file.' 10 | validate do |value| 11 | raise _('bundle files should be a string') unless value.is_a? String 12 | end 13 | end 14 | 15 | newparam(:compose_files, array_matching: :all) do 16 | desc 'An array of Docker Compose Files paths.' 17 | validate do |value| 18 | raise _('compose files should be an array') unless value.is_a? Array 19 | end 20 | end 21 | 22 | newparam(:up_args) do 23 | desc 'Arguments to be passed directly to docker stack deploy.' 24 | validate do |value| 25 | raise _('up_args should be a String') unless value.is_a? String 26 | end 27 | end 28 | 29 | newparam(:name) do 30 | isnamevar 31 | desc 'The name of the stack' 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/puppet/type/docker_volume.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:docker_volume) do 4 | @doc = 'A type representing a Docker volume' 5 | ensurable 6 | 7 | newparam(:name) do 8 | isnamevar 9 | desc 'The name of the volume' 10 | end 11 | 12 | newproperty(:driver) do 13 | desc 'The volume driver used by the volume' 14 | end 15 | 16 | newparam(:options) do 17 | desc 'Additional options for the volume driver' 18 | end 19 | 20 | newproperty(:mountpoint) do 21 | desc 'The location that the volume is mounted to' 22 | validate do |value| 23 | raise(Puppet::ParseError, "#{value} is read-only and is only available via puppet resource.") 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /manifests/compose.pp: -------------------------------------------------------------------------------- 1 | # @summary install Docker Compose using the recommended curl command. 2 | # 3 | # @param ensure 4 | # Whether to install or remove Docker Compose 5 | # Valid values are absent present 6 | # 7 | # @param version 8 | # The version of Docker Compose to install. 9 | # 10 | class docker::compose ( 11 | Enum[present,absent] $ensure = present, 12 | Optional[String] $version = undef, 13 | ) { 14 | include docker 15 | 16 | if $docker::manage_package { 17 | include docker::params 18 | 19 | $_version = $version ? { 20 | undef => $docker::params::compose_version, 21 | default => $version, 22 | } 23 | if $_version and $ensure != 'absent' { 24 | $package_ensure = $_version 25 | } else { 26 | $package_ensure = $ensure 27 | } 28 | 29 | case $facts['os']['family'] { 30 | 'Debian': { 31 | $_require = $docker::use_upstream_package_source ? { 32 | true => [Apt::Source['docker'], Class['apt::update']], 33 | false => undef, 34 | } 35 | } 36 | 'RedHat': { 37 | $_require = $docker::use_upstream_package_source ? { 38 | true => Yumrepo['docker'], 39 | false => undef, 40 | } 41 | } 42 | 'Windows': { 43 | fail('The docker compose portion of this module is not supported on Windows') 44 | } 45 | default: { 46 | fail('The docker compose portion of this module only works on Debian or RedHat') 47 | } 48 | } 49 | package { 'docker-compose-plugin': 50 | ensure => $package_ensure, 51 | require => $_require, 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /manifests/config.pp: -------------------------------------------------------------------------------- 1 | # @summary Configuration for docker 2 | # @api private 3 | # 4 | class docker::config { 5 | if $facts['os']['family'] != 'windows' { 6 | $docker::docker_users.each |$user| { 7 | docker::system_user { $user: 8 | create_user => $docker::create_user, 9 | } 10 | } 11 | } else { 12 | $docker::docker_users.each |$user| { 13 | docker::windows_account { $user: } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /manifests/exec.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # A define which executes a command inside a container. 3 | # 4 | # @param detach 5 | # @param interactive 6 | # @param env 7 | # @param tty 8 | # @param container 9 | # @param command 10 | # @param unless 11 | # @param sanitise_name 12 | # @param refreshonly 13 | # @param onlyif 14 | # 15 | define docker::exec ( 16 | Boolean $detach = false, 17 | Boolean $interactive = false, 18 | Array $env = [], 19 | Boolean $tty = false, 20 | Optional[String] $container = undef, 21 | Optional[String] $command = undef, 22 | Optional[String] $unless = undef, 23 | Boolean $sanitise_name = true, 24 | Boolean $refreshonly = false, 25 | Optional[String] $onlyif = undef, 26 | ) { 27 | include docker::params 28 | 29 | $docker_command = $docker::params::docker_command 30 | 31 | if $facts['os']['family'] == 'windows' { 32 | $exec_environment = "PATH=${facts['docker_program_files_path']}/Docker/" 33 | $exec_timeout = 3000 34 | $exec_path = ["${facts['docker_program_files_path']}/Docker/",] 35 | $exec_provider = 'powershell' 36 | } else { 37 | $exec_environment = 'HOME=/root' 38 | $exec_path = ['/bin', '/usr/bin',] 39 | $exec_timeout = 0 40 | $exec_provider = undef 41 | } 42 | 43 | $docker_exec_flags = docker_exec_flags({ 44 | detach => $detach, 45 | interactive => $interactive, 46 | tty => $tty, 47 | env => any2array($env), 48 | } 49 | ) 50 | 51 | if $sanitise_name { 52 | $sanitised_container = regsubst($container, '[^0-9A-Za-z.\-_]', '-', 'G') 53 | } else { 54 | $sanitised_container = $container 55 | } 56 | 57 | $exec = "${docker_command} exec ${docker_exec_flags} ${sanitised_container} ${command}" 58 | 59 | $unless_command = $unless ? { 60 | undef => undef, 61 | '' => undef, 62 | default => "${docker_command} exec ${docker_exec_flags} ${sanitised_container} ${$unless}", 63 | } 64 | 65 | $onlyif_command = $onlyif ? { 66 | undef => undef, 67 | '' => undef, 68 | 'running' => "${docker_command} ps --no-trunc --format='table {{.Names}}' | grep '^${sanitised_container}$'", 69 | default => $onlyif 70 | } 71 | 72 | exec { $exec: 73 | environment => $exec_environment, 74 | onlyif => $onlyif_command, 75 | path => $exec_path, 76 | refreshonly => $refreshonly, 77 | timeout => $exec_timeout, 78 | provider => $exec_provider, 79 | unless => $unless_command, 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /manifests/images.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param images 4 | # 5 | class docker::images ( 6 | Hash $images 7 | ) { 8 | create_resources(docker::image, $images) 9 | } 10 | -------------------------------------------------------------------------------- /manifests/networks.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param networks 4 | # 5 | class docker::networks ( 6 | Optional[Hash[String, Hash]] $networks = undef, 7 | ) { 8 | if $networks { 9 | create_resources(docker_network, $networks) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /manifests/plugins.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param plugins 4 | # 5 | class docker::plugins ( 6 | Hash $plugins 7 | ) { 8 | create_resources(docker::plugin, $plugins) 9 | } 10 | -------------------------------------------------------------------------------- /manifests/registry_auth.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param registries 4 | # 5 | class docker::registry_auth ( 6 | Hash $registries 7 | ) { 8 | create_resources(docker::registry, $registries) 9 | } 10 | -------------------------------------------------------------------------------- /manifests/repos.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param location 4 | # 5 | # @param key_source 6 | # 7 | # @param key_check_source 8 | # 9 | # @param architecture 10 | # 11 | class docker::repos ( 12 | Optional[String] $location = $docker::package_location, 13 | Optional[String] $key_source = $docker::package_key_source, 14 | Optional[Boolean] $key_check_source = $docker::package_key_check_source, 15 | String $architecture = $facts['os']['architecture'], 16 | ) { 17 | stdlib::ensure_packages($docker::prerequired_packages) 18 | 19 | case $facts['os']['family'] { 20 | 'Debian': { 21 | $release = $docker::release 22 | $package_key = $docker::package_key 23 | $package_repos = $docker::package_repos 24 | 25 | if ($docker::use_upstream_package_source) { 26 | apt::source { 'docker': 27 | location => $location, 28 | architecture => $architecture, 29 | release => $release, 30 | repos => $package_repos, 31 | key => { 32 | id => $package_key, 33 | source => $key_source, 34 | }, 35 | include => { 36 | src => false, 37 | }, 38 | } 39 | 40 | $url_split = split($location, '/') 41 | $repo_host = $url_split[2] 42 | $pin_ensure = $docker::pin_upstream_package_source ? { 43 | true => 'present', 44 | default => 'absent', 45 | } 46 | 47 | apt::pin { 'docker': 48 | ensure => $pin_ensure, 49 | origin => $repo_host, 50 | priority => $docker::apt_source_pin_level, 51 | } 52 | 53 | if $docker::manage_package { 54 | include apt 55 | 56 | if (versioncmp($facts['facterversion'], '2.4.6') <= 0) { 57 | if $facts['os']['name'] == 'Debian' and $facts['os']['lsb']['distcodename'] == 'wheezy' { 58 | include apt::backports 59 | } 60 | } else { 61 | if $facts['os']['name'] == 'Debian' and $facts['os']['distro']['codename'] == 'wheezy' { 62 | include apt::backports 63 | } 64 | } 65 | Exec['apt_update'] -> Package[$docker::prerequired_packages] 66 | Apt::Source['docker'] -> Package['docker'] 67 | } 68 | } 69 | } 70 | 'RedHat': { 71 | if ($docker::manage_package) { 72 | $baseurl = $location 73 | $gpgkey = $key_source 74 | $gpgkey_check = $key_check_source 75 | 76 | if ($docker::use_upstream_package_source) { 77 | yumrepo { 'docker': 78 | descr => 'Docker', 79 | baseurl => $baseurl, 80 | gpgkey => $gpgkey, 81 | gpgcheck => $gpgkey_check, 82 | } 83 | 84 | Yumrepo['docker'] -> Package['docker'] 85 | } 86 | } 87 | } 88 | default: {} 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /manifests/run_instance.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param instance 4 | # 5 | class docker::run_instance ( 6 | Hash $instance 7 | ) { 8 | create_resources(docker::run, $instance) 9 | } 10 | -------------------------------------------------------------------------------- /manifests/secrets.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param ensure 4 | # 5 | # @param label 6 | # 7 | # @param secret_name 8 | # 9 | # @param secret_path 10 | # 11 | define docker::secrets ( 12 | Enum[present,absent] $ensure = 'present', 13 | Variant[String,Array] $label = [], 14 | Optional[String] $secret_name = undef, 15 | Optional[String] $secret_path = undef, 16 | ) { 17 | include docker::params 18 | 19 | $docker_command = "${docker::params::docker_command} secret" 20 | 21 | if $ensure == 'present' { 22 | $docker_secrets_flags = docker_secrets_flags({ 23 | ensure => $ensure, 24 | label => $label, 25 | secret_name => $secret_name, 26 | secret_path => $secret_path, 27 | } 28 | ) 29 | 30 | $exec_secret = "${docker_command} ${docker_secrets_flags}" 31 | $unless_secret = "${docker_command} inspect ${secret_name}" 32 | 33 | exec { "${title} docker secret create": 34 | command => $exec_secret, 35 | unless => $unless_secret, 36 | path => ['/bin', '/usr/bin',], 37 | } 38 | } 39 | 40 | if $ensure == 'absent' { 41 | exec { "${title} docker secret rm": 42 | command => "${docker_command} rm ${secret_name}", 43 | onlyif => "${docker_command} inspect ${secret_name}", 44 | path => ['/bin', '/usr/bin',], 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /manifests/stack.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # deploys Docker stacks or compose v3 3 | # 4 | # @param ensure 5 | # This ensures that the stack is present or not. 6 | # 7 | # @param stack_name 8 | # The name of the stack that you are deploying 9 | # 10 | # @param bundle_file 11 | # Path to a Distributed Application Bundle file 12 | # Please note this is experimental 13 | # 14 | # @param prune 15 | # Prune services that are no longer referenced 16 | # 17 | # @param resolve_image 18 | # Query the registry to resolve image digest and supported platforms 19 | # Only accepts ("always"|"changed"|"never") 20 | # 21 | # @param with_registry_auth 22 | # Send registry authentication details to Swarm agents 23 | # 24 | # @param compose_files 25 | define docker::stack ( 26 | Enum[present,absent] $ensure = 'present', 27 | Optional[String] $stack_name = undef, 28 | Optional[String] $bundle_file = undef, 29 | Optional[Array] $compose_files = undef, 30 | Boolean $prune = false, 31 | Boolean $with_registry_auth = false, 32 | Optional[Enum['always','changed','never']] $resolve_image = undef, 33 | ) { 34 | include docker::params 35 | 36 | deprecation('docker::stack','The docker stack define type will be deprecated in a future release. Please migrate to the docker_stack type/provider.') 37 | 38 | $docker_command = "${docker::params::docker_command} stack" 39 | 40 | if $facts['os']['family'] == 'windows' { 41 | $exec_path = ['C:/Program Files/Docker/',] 42 | $check_stack = '$info = docker stack ls | select-string -pattern web 43 | if ($info -eq $null) { Exit 1 } else { Exit 0 }' 44 | $provider = 'powershell' 45 | } else { 46 | $exec_path = ['/bin', '/usr/bin',] 47 | $check_stack = "${docker_command} ls | grep '${stack_name}'" 48 | $provider = undef 49 | } 50 | 51 | if $ensure == 'present' { 52 | $docker_stack_flags = docker_stack_flags ({ 53 | stack_name => $stack_name, 54 | bundle_file => $bundle_file, 55 | compose_files => $compose_files, 56 | prune => $prune, 57 | with_registry_auth => $with_registry_auth, 58 | resolve_image => $resolve_image, 59 | } 60 | ) 61 | 62 | $exec_stack = "${docker_command} deploy ${docker_stack_flags} ${stack_name}" 63 | 64 | exec { "docker stack create ${stack_name}": 65 | command => $exec_stack, 66 | unless => $check_stack, 67 | path => $exec_path, 68 | provider => $provider, 69 | } 70 | } 71 | 72 | if $ensure == 'absent' { 73 | exec { "docker stack destroy ${stack_name}": 74 | command => "${docker_command} rm ${stack_name}", 75 | onlyif => $check_stack, 76 | path => $exec_path, 77 | provider => $provider, 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /manifests/swarms.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param swarms 4 | # 5 | class docker::swarms ( 6 | Hash $swarms 7 | ) { 8 | create_resources(docker::swarm, $swarms) 9 | } 10 | -------------------------------------------------------------------------------- /manifests/system_user.pp: -------------------------------------------------------------------------------- 1 | # @summary manage docker group users 2 | # 3 | # @param create_user 4 | # Boolean to cotrol whether the user should be created 5 | # 6 | define docker::system_user ( 7 | Boolean $create_user = true 8 | ) { 9 | include docker 10 | 11 | $docker_group = $docker::docker_group 12 | 13 | if $create_user { 14 | ensure_resource('user', $name, { 'ensure' => 'present' }) 15 | 16 | User[$name] -> Exec["docker-system-user-${name}"] 17 | } 18 | 19 | exec { "docker-system-user-${name}": 20 | command => "/usr/sbin/usermod -aG ${docker_group} ${name}", 21 | unless => "/bin/cat /etc/group | grep '^${docker_group}:' | grep -qw ${name}", 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /manifests/systemd_reload.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # For systems that have systemd 3 | # 4 | class docker::systemd_reload { 5 | exec { 'docker-systemd-reload': 6 | path => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/',], 7 | command => 'systemctl daemon-reload', 8 | refreshonly => true, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /manifests/volumes.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # 3 | # @param volumes 4 | # 5 | class docker::volumes ( 6 | Hash $volumes 7 | ) { 8 | create_resources(docker_volume, $volumes) 9 | } 10 | -------------------------------------------------------------------------------- /manifests/windows_account.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # Windows account that owns the docker services 3 | # 4 | define docker::windows_account ( 5 | ) { 6 | notice('Not implemented') 7 | } 8 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppetlabs-docker", 3 | "version": "10.3.0", 4 | "author": "puppetlabs", 5 | "summary": "Module for installing and managing docker", 6 | "license": "Apache-2.0", 7 | "source": "https://github.com/puppetlabs/puppetlabs-docker", 8 | "project_page": "https://github.com/puppetlabs/puppetlabs-docker", 9 | "issues_url": "https://github.com/puppetlabs/puppetlabs-docker/issues", 10 | "dependencies": [ 11 | { 12 | "name": "puppetlabs/stdlib", 13 | "version_requirement": ">= 9.0.0 < 10.0.0" 14 | }, 15 | { 16 | "name": "puppetlabs/apt", 17 | "version_requirement": ">= 4.4.1 < 11.0.0" 18 | }, 19 | { 20 | "name": "puppetlabs/powershell", 21 | "version_requirement": ">= 2.1.4 < 7.0.0" 22 | }, 23 | { 24 | "name": "puppetlabs/reboot", 25 | "version_requirement": ">=2.0.0 < 6.0.0" 26 | } 27 | ], 28 | "operatingsystem_support": [ 29 | { 30 | "operatingsystem": "CentOS", 31 | "operatingsystemrelease": [ 32 | "7", 33 | "8", 34 | "9" 35 | ] 36 | }, 37 | { 38 | "operatingsystem": "Ubuntu", 39 | "operatingsystemrelease": [ 40 | "18.04", 41 | "20.04", 42 | "22.04" 43 | ] 44 | }, 45 | { 46 | "operatingsystem": "Debian", 47 | "operatingsystemrelease": [ 48 | "10", 49 | "11" 50 | ] 51 | }, 52 | { 53 | "operatingsystem": "Windows", 54 | "operatingsystemrelease": [ 55 | "2016", 56 | "2019", 57 | "2022" 58 | ] 59 | } 60 | ], 61 | "requirements": [ 62 | { 63 | "name": "puppet", 64 | "version_requirement": ">= 7.0.0 < 9.0.0" 65 | } 66 | ], 67 | "pdk-version": "3.0.0", 68 | "template-url": "https://github.com/puppetlabs/pdk-templates.git#main", 69 | "template-ref": "heads/main-0-g79a2f93" 70 | } 71 | -------------------------------------------------------------------------------- /pdk.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore: [] 3 | -------------------------------------------------------------------------------- /provision.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | default: 3 | provisioner: vagrant 4 | images: 5 | - ubuntu/xenial64 6 | - ubuntu/bionic64 7 | centos: 8 | provisioner: vagrant 9 | images: 10 | - centos/7 11 | debian: 12 | provisioner: vagrant 13 | images: 14 | - debian/stretch64 15 | - debian/buster64 16 | win: 17 | provisioner: vagrant 18 | images: 19 | - gusztavvargadr/windows-server 20 | release_checks_6: 21 | provisioner: abs 22 | images: 23 | - redhat-7-x86_64 24 | - centos-7-x86_64 25 | - ubuntu-1604-x86_64 26 | - ubuntu-1804-x86_64 27 | - ubuntu-2004-x86_64 28 | - debian-9-x86_64 29 | - debian-10-x86_64 30 | - win-2016-x86_64 31 | - win-2019-x86_64 32 | release_checks_7: 33 | provisioner: abs 34 | images: 35 | - centos-7-x86_64 36 | - ubuntu-1804-x86_64 37 | - ubuntu-2004-x86_64 38 | - debian-10-x86_64 39 | - win-2016-x86_64 40 | - win-2019-x86_64 41 | -------------------------------------------------------------------------------- /spec/acceptance/docker_custom_source_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | if os[:family] == 'windows' 6 | docker_args = 'docker_ee => true, docker_ee_source_location => "https://download.docker.com/components/engine/windows-server/17.06/docker-17.06.2-ee-14.zip"' 7 | default_image = 'winamd64/hello-seattle' 8 | # The default args are set because: 9 | # restart => 'always' - there is no service created to manage containers 10 | # net => 'nat' - docker uses bridged by default when running a container. When installing docker on windows the default network is NAT. 11 | default_docker_run_arg = "restart => 'always', net => 'nat'," 12 | default_run_command = 'ping 127.0.0.1 -t' 13 | docker_command = '"/cygdrive/c/Program Files/Docker/docker"' 14 | else 15 | docker_args = '' 16 | default_image = 'busybox' 17 | end 18 | skip = false 19 | 20 | describe 'the Puppet Docker module' do 21 | context 'with download location', skip: skip do 22 | let(:pp) do 23 | "class { 'docker': #{docker_args} }" 24 | end 25 | 26 | it 'runs successfully' do 27 | apply_manifest(pp, catch_failures: true) 28 | end 29 | 30 | it 'runs idempotently' do 31 | apply_manifest(pp, catch_changes: true) unless selinux == 'true' 32 | end 33 | 34 | it 'is start a docker process' do 35 | if os[:family] == 'windows' 36 | run_shell('powershell Get-Process -Name dockerd') do |r| 37 | expect(r.stdout).to match(%r{ProcessName}) 38 | end 39 | else 40 | run_shell('ps aux | grep docker') do |r| 41 | expect(r.stdout).to match %r{dockerd -H unix:///var/run/docker.sock} 42 | end 43 | end 44 | end 45 | 46 | it 'installs a working docker client' do 47 | run_shell("#{docker_command} ps", expect_failures: false) 48 | end 49 | 50 | it 'stops a running container and remove container' do 51 | pp = <<-EOS 52 | class { 'docker': #{docker_args} } 53 | 54 | docker::image { '#{default_image}': 55 | require => Class['docker'], 56 | } 57 | 58 | docker::run { 'container_3_6': 59 | image => '#{default_image}', 60 | command => '#{default_run_command}', 61 | require => Docker::Image['#{default_image}'], 62 | #{default_docker_run_arg} 63 | } 64 | EOS 65 | 66 | pp2 = <<-EOS 67 | class { 'docker': #{docker_args} } 68 | 69 | docker::image { '#{default_image}': 70 | require => Class['docker'], 71 | } 72 | 73 | docker::run { 'container_3_6': 74 | ensure => 'absent', 75 | image => '#{default_image}', 76 | require => Docker::Image['#{default_image}'], 77 | } 78 | EOS 79 | 80 | apply_manifest(pp, catch_failures: true) 81 | apply_manifest(pp) unless selinux == 'true' 82 | 83 | # A sleep to give docker time to execute properly 84 | sleep 15 85 | 86 | run_shell("#{docker_command} ps", expect_failures: false) 87 | 88 | apply_manifest(pp2, catch_failures: true) 89 | apply_manifest(pp2, catch_changes: true) unless selinux == 'true' 90 | 91 | # A sleep to give docker time to execute properly 92 | sleep 15 93 | 94 | run_shell("#{docker_command} inspect container-3-6", expect_failures: true) 95 | if os[:family] == 'windows' 96 | run_shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', expect_failures: true) 97 | else 98 | run_shell('test -f /etc/systemd/system/container-3-6.service', expect_failures: true) 99 | end 100 | end 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /spec/acceptance/machine_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'docker::machine', :win_broken do 6 | context 'with default parameters' do 7 | pp = <<-EOS 8 | include docker::machine 9 | EOS 10 | 11 | it 'applies with no errors' do 12 | apply_manifest(pp, catch_failures: true) 13 | end 14 | 15 | it 'is idempotent' do 16 | apply_manifest(pp, catch_changes: true) 17 | end 18 | 19 | it 'machine configurable check of docker-machine-0.16.1' do 20 | expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_file 21 | expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_owned_by 'root' 22 | expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_mode 755 23 | end 24 | 25 | it 'machine configurable check of docker-machine' do 26 | expect(file('/usr/local/bin/docker-machine')).to be_linked_to '/usr/local/bin/docker-machine-0.16.1' 27 | expect(file('/usr/local/bin/docker-machine')).to be_symlink 28 | end 29 | 30 | it 'is installed and working' do 31 | run_shell('docker-machine --help', expect_failures: false) 32 | end 33 | end 34 | 35 | context 'with url => https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.3/docker-machine' do 36 | pp = <<-EOS 37 | class { 'docker::machine': 38 | version => '0.16.2-gitlab.3', 39 | url => 'https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.3/docker-machine', 40 | } 41 | EOS 42 | 43 | it 'applies with no errors' do 44 | apply_manifest(pp, catch_failures: true) 45 | end 46 | 47 | it 'is idempotent' do 48 | apply_manifest(pp, catch_changes: true) 49 | end 50 | 51 | it 'machine configurable check of docker-machine-0.16.2-gitlab.3' do 52 | expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_file 53 | expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_owned_by 'root' 54 | expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_mode 755 55 | end 56 | 57 | it 'machine configurable check of docker-machine' do 58 | expect(file('/usr/local/bin/docker-machine')).to be_linked_to '/usr/local/bin/docker-machine-0.16.2-gitlab.3' 59 | expect(file('/usr/local/bin/docker-machine')).to be_symlink 60 | end 61 | 62 | it 'is installed and working' do 63 | run_shell('docker-machine --help', expect_failures: false) 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /spec/acceptance/network_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | broken = false 6 | command = 'docker' 7 | network_name = 'test-network' 8 | 9 | if os[:family] == 'windows' 10 | puts 'Not implemented on Windows' 11 | broken = true 12 | docker_args = '' 13 | end 14 | 15 | describe 'docker network', win_broken: broken do 16 | before(:all) do 17 | install_pp = "class { 'docker': #{docker_args}}" 18 | apply_manifest(install_pp, catch_failures: true) 19 | end 20 | 21 | it "#{command} network --help" do 22 | run_shell("#{command} network --help", expect_failures: false) 23 | end 24 | 25 | context 'with a local bridge network described in Puppet' do 26 | after(:all) do 27 | run_shell("#{command} network rm #{network_name}") 28 | end 29 | 30 | it 'is idempotent' do 31 | pp = <<-MANIFEST 32 | docker_network { '#{network_name}': 33 | ensure => present, 34 | } 35 | MANIFEST 36 | idempotent_apply(pp) 37 | end 38 | 39 | it 'has created a network' do 40 | run_shell("#{command} network inspect #{network_name}", expect_failures: false) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/acceptance/plugin_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | broken = false 6 | command = 'docker' 7 | plugin_name = 'vieux/sshfs' 8 | 9 | if os[:family] == 'windows' 10 | puts 'Not implemented on Windows' 11 | broken = true 12 | else 13 | docker_args = '' 14 | end 15 | 16 | describe 'docker plugin', win_broken: broken do 17 | before(:all) do 18 | install_code = "class { 'docker': #{docker_args}}" 19 | apply_manifest(install_code, catch_failures: true) 20 | end 21 | 22 | it "#{command} plugin --help" do 23 | run_shell("#{command} plugin --help", expect_failures: false) 24 | end 25 | 26 | context 'manage a plugin' do 27 | after(:all) do 28 | run_shell("#{command} plugin rm -f #{plugin_name}") 29 | end 30 | 31 | it 'is idempotent' do 32 | pp = <<-MANIFEST 33 | docker::plugin { '#{plugin_name}':} 34 | MANIFEST 35 | idempotent_apply(pp) 36 | end 37 | 38 | it 'has installed a plugin' do 39 | run_shell("#{command} plugin inspect #{plugin_name}", expect_failures: false) 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/acceptance/volume_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | volume_name = 'test-volume' 6 | 7 | if os[:family] == 'windows' 8 | docker_args = 'docker_ee => true' 9 | command = '"/cygdrive/c/Program Files/Docker/docker"' 10 | else 11 | docker_args = '' 12 | command = 'docker' 13 | end 14 | 15 | describe 'docker volume' do 16 | before(:all) do 17 | retry_on_error_matching(60, 5, %r{connection failure running}) do 18 | install_pp = "class { 'docker': #{docker_args} }" 19 | apply_manifest(install_pp, catch_failures: true) 20 | end 21 | end 22 | 23 | it 'exposes volume subcommand' do 24 | run_shell("#{command} volume --help", expect_failures: false) 25 | end 26 | 27 | context 'with a local volume described in Puppet' do 28 | after(:all) do 29 | run_shell("#{command} volume rm #{volume_name}") 30 | end 31 | 32 | it 'applies idempotently' do 33 | pp = <<-MANIFEST 34 | docker_volume { '#{volume_name}': 35 | ensure => present, 36 | } 37 | MANIFEST 38 | 39 | idempotent_apply(pp) 40 | end 41 | 42 | it 'has created a volume' do 43 | run_shell("#{command} volume inspect #{volume_name}", expect_failures: false) 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/acceptance_swarm/default.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-1604: 3 | roles: 4 | - default 5 | - swarm-manager 6 | platform: ubuntu-16.04-amd64 7 | hypervisor: vmpooler 8 | template: Delivery/Quality Assurance/Templates/vCloud/ubuntu-1604-x86_64 9 | ubuntu-1604-a: 10 | roles: 11 | - swarm-worker 12 | platform: ubuntu-16.04-amd64 13 | hypervisor: vmpooler 14 | template: Delivery/Quality Assurance/Templates/vCloud/ubuntu-1604-x86_64 15 | CONFIG: 16 | nfs_server: none 17 | consoleport: 443 18 | datastore: instance0 19 | folder: Delivery/Quality Assurance/Enterprise/Dynamic 20 | resourcepool: delivery/Quality Assurance/Enterprise/Dynamic 21 | pooling_api: http://vcloud.delivery.puppetlabs.net/ 22 | type: foss -------------------------------------------------------------------------------- /spec/acceptance_swarm/nodesets/pooler/ubuntu-1604.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-1604: 3 | roles: 4 | - default 5 | - swarm-manager 6 | platform: ubuntu-16.04-amd64 7 | hypervisor: vmpooler 8 | template: Delivery/Quality Assurance/Templates/vCloud/ubuntu-1604-x86_64 9 | ubuntu-1604-a: 10 | roles: 11 | - swarm-worker 12 | platform: ubuntu-16.04-amd64 13 | hypervisor: vmpooler 14 | template: Delivery/Quality Assurance/Templates/vCloud/ubuntu-1604-x86_64 15 | CONFIG: 16 | nfs_server: none 17 | consoleport: 443 18 | datastore: instance0 19 | folder: Delivery/Quality Assurance/Enterprise/Dynamic 20 | resourcepool: delivery/Quality Assurance/Enterprise/Dynamic 21 | pooling_api: http://vcloud.delivery.puppetlabs.net/ 22 | type: foss -------------------------------------------------------------------------------- /spec/acceptance_swarm/nodesets/pooler/win-2016.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-1604: 3 | roles: 4 | - master 5 | - database 6 | - dashboard 7 | platform: ubuntu-16.04-amd64 8 | hypervisor: vmpooler 9 | template: Delivery/Quality Assurance/Templates/vCloud/ubuntu-1604-x86_64 10 | win-2016: 11 | roles: 12 | - default 13 | - agent 14 | - swarm-manager 15 | platform: windows-2016-x86_64 16 | hypervisor: vmpooler 17 | template: Delivery/Quality Assurance/Templates/vCloud/win-2016-x86_64 18 | win-2016-a: 19 | roles: 20 | - agent 21 | - swarm-worker 22 | platform: windows-2016-x86_64 23 | hypervisor: vmpooler 24 | template: Delivery/Quality Assurance/Templates/vCloud/win-2016-x86_64 25 | CONFIG: 26 | nfs_server: none 27 | consoleport: 443 28 | datastore: instance0 29 | folder: Delivery/Quality Assurance/Enterprise/Dynamic 30 | resourcepool: delivery/Quality Assurance/Enterprise/Dynamic 31 | pooling_api: http://vcloud.delivery.puppetlabs.net/ 32 | type: foss 33 | -------------------------------------------------------------------------------- /spec/classes/compose_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'with default valus' => {}, 7 | 'with ensure => absent' => { 8 | 'ensure' => 'absent' 9 | }, 10 | 'with version => 1.7.0' => { 11 | 'version' => '1.7.0' 12 | } 13 | } 14 | 15 | describe 'docker::compose', type: :class do 16 | on_supported_os.each do |os, os_facts| 17 | ## 18 | ## set some needed facts 19 | ## 20 | facts = if os.include?('windows') 21 | windows_facts.merge(os_facts) 22 | else 23 | os_facts 24 | end 25 | 26 | ## 27 | ## get defaults values from params 28 | ## 29 | defaults = get_defaults(facts) 30 | 31 | context "on #{os}" do 32 | tests.each do |title, local_params| 33 | context title do 34 | params = { 35 | 'ensure' => 'present', 36 | 'version' => defaults['compose_version'] 37 | }.merge(local_params) 38 | 39 | let(:facts) do 40 | facts 41 | end 42 | 43 | let(:params) do 44 | params 45 | end 46 | 47 | include_examples 'compose', params, facts 48 | end 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/classes/images_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'with ensure => present' => { 7 | 'ensure' => 'present' 8 | }, 9 | 'with ensure => absent' => { 10 | 'ensure' => 'absent' 11 | } 12 | } 13 | 14 | describe 'docker::images', type: :class do 15 | on_supported_os.each do |os, os_facts| 16 | ## 17 | ## set some needed facts 18 | ## 19 | facts = if os.include?('windows') 20 | windows_facts.merge(os_facts) 21 | else 22 | os_facts 23 | end 24 | 25 | ## 26 | ## get defaults values from params 27 | ## 28 | defaults = get_defaults(facts) 29 | 30 | context "on #{os}" do 31 | tests.each do |title, local_params| 32 | context title do 33 | params = { 34 | 'base' => { 35 | 'ensure' => 'present', 36 | 'image_tag' => :undef, 37 | 'image_digest' => :undef, 38 | 'force' => false, 39 | 'docker_file' => :undef, 40 | 'docker_dir' => :undef, 41 | 'docker_tar' => :undef 42 | } 43 | } 44 | 45 | params.each do |key, values| 46 | values.merge!(local_params.merge('image' => key)) 47 | 48 | let(:facts) do 49 | facts 50 | end 51 | 52 | let(:params) do 53 | { 54 | 'images' => { 55 | key => values 56 | } 57 | } 58 | end 59 | 60 | include_examples 'image', values, facts, defaults 61 | 62 | it { 63 | expect(subject).to contain_docker__image(key) 64 | } 65 | end 66 | end 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /spec/classes/machine_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | # Need to write test casees here 5 | tests = { 6 | 'with default value' => {} 7 | } 8 | 9 | describe 'docker::machine', type: :class do 10 | on_supported_os.each do |os, os_facts| 11 | ## 12 | ## set some needed facts 13 | ## 14 | facts = if os.include?('windows') 15 | windows_facts.merge(os_facts) 16 | else 17 | os_facts 18 | end 19 | 20 | ## 21 | ## get defaults values from params 22 | ## 23 | defaults = get_defaults(facts) 24 | 25 | context "on #{os}" do 26 | tests.each do |title, local_params| 27 | context title do 28 | params = { 29 | 'ensure' => 'present', 30 | 'version' => defaults['machine_version'], 31 | 'install_path' => defaults['machine_install_path'], 32 | 'proxy' => :undef, 33 | 'url' => :undef, 34 | 'curl_ensure' => defaults['curl_ensure'] 35 | }.merge(local_params) 36 | 37 | let(:facts) do 38 | facts 39 | end 40 | 41 | let(:params) do 42 | params 43 | end 44 | 45 | # Need to write check condition for params['proxy'] 46 | # The block commented below currently has no test case, if in future more test cases are added to this spec file, please refer to spec/classes/compose_spec.rb and implement as required here. 47 | # if title == 'when proxy is not a http proxy' 48 | # it 'raises an error for invalid proxy URL' do 49 | # is_expected.to compile.and_raise_error( 50 | # %r{parameter 'proxy' expects an undef value or a match for Pattern}, 51 | # ) 52 | # end 53 | # else 54 | # include_examples 'machine', params, facts, defaults 55 | # end 56 | include_examples 'machine', params, facts, defaults 57 | end 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /spec/classes/networks_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'network-present' => { 7 | 'ensure' => 'present', 8 | 'driver' => 'overlay', 9 | 'subnet' => '192.168.1.0/24', 10 | 'gateway' => '192.168.1.1', 11 | 'ip_range' => '192.168.1.4/32' 12 | }, 13 | 'network-absent' => { 14 | 'ensure' => 'absent', 15 | 'driver' => 'overlay', 16 | 'subnet' => '192.168.1.0/24', 17 | 'gateway' => '192.168.1.1', 18 | 'ip_range' => '192.168.1.4/32' 19 | } 20 | } 21 | 22 | describe 'docker::networks', type: :class do 23 | on_supported_os.each do |os, os_facts| 24 | ## 25 | ## set some needed facts 26 | ## 27 | facts = if os.include?('windows') 28 | windows_facts.merge(os_facts) 29 | else 30 | os_facts 31 | end 32 | 33 | ## 34 | ## get defaults values from params 35 | ## 36 | defaults = get_defaults(facts) 37 | 38 | context "on #{os}" do 39 | tests.each do |title, local_params| 40 | context title do 41 | params = local_params 42 | 43 | let(:facts) do 44 | facts 45 | end 46 | 47 | let(:params) do 48 | { 49 | 'networks' => { 50 | title => local_params 51 | } 52 | } 53 | end 54 | 55 | it { 56 | expect(subject).to contain_docker_network(title).with( 57 | 'ensure' => params['ensure'], 58 | 'driver' => params['driver'], 59 | 'subnet' => params['subnet'], 60 | 'gateway' => params['gateway'], 61 | 'ip_range' => params['ip_range'], 62 | ) 63 | } 64 | 65 | it { is_expected.to have_docker_network_resource_count(1) } 66 | end 67 | end 68 | 69 | context 'with no params' do 70 | it { is_expected.to have_docker_network_resource_count(0) } 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /spec/classes/plugins_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'foo/enabled:latest' => { 7 | 'enabled' => true 8 | }, 9 | 'foo/disabled:latest' => { 10 | 'enabled' => false 11 | } 12 | } 13 | 14 | describe 'docker::plugins', type: :class do 15 | on_supported_os.each do |os, os_facts| 16 | ## 17 | ## set some needed facts 18 | ## 19 | facts = if os.include?('windows') 20 | windows_facts.merge(os_facts) 21 | else 22 | os_facts 23 | end 24 | 25 | ## 26 | ## get defaults values from params 27 | ## 28 | defaults = get_defaults(facts) 29 | 30 | context "on #{os}" do 31 | tests.each do |title, local_params| 32 | context title do 33 | params = { 34 | 'base' => { 35 | 'ensure' => 'present', 36 | 'enabled' => true, 37 | 'timeout' => :undef, 38 | 'plugin_alias' => :undef, 39 | 'disable_on_install' => false, 40 | 'disable_content_trust' => true, 41 | 'grant_all_permissions' => true, 42 | 'force_remove' => true, 43 | 'settings' => [] 44 | } 45 | } 46 | 47 | params.each do |key, values| 48 | values.merge!(local_params.merge('plugin_name' => key)) 49 | 50 | let(:facts) do 51 | facts 52 | end 53 | 54 | let(:params) do 55 | { 56 | 'plugins' => { 57 | key => values 58 | } 59 | } 60 | end 61 | 62 | if facts[:os]['family'] == 'windows' 63 | it { 64 | expect(subject).to compile.and_raise_error(%r{Feature not implemented on windows.}) 65 | } 66 | 67 | next 68 | end 69 | 70 | include_examples 'plugin', values, facts, defaults 71 | 72 | it { 73 | expect(subject).to contain_docker__plugin(key) 74 | } 75 | end 76 | end 77 | end 78 | end 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /spec/default_facts.yml: -------------------------------------------------------------------------------- 1 | # Use default_module_facts.yml for module specific facts. 2 | # 3 | # Facts specified here will override the values provided by rspec-puppet-facts. 4 | --- 5 | networking: 6 | ip: "172.16.254.254" 7 | ip6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA" 8 | mac: "AA:AA:AA:AA:AA:AA" 9 | is_pe: false 10 | -------------------------------------------------------------------------------- /spec/defines/exec_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'with default values' => {}, 7 | 'when running detached' => { 8 | 'detach' => true 9 | }, 10 | 'when running with tty' => { 11 | 'tty' => true 12 | }, 13 | 'when running with interactive' => { 14 | 'interactive' => true 15 | }, 16 | 'when running with onlyif "running"' => { 17 | 'interactive' => true, 18 | 'onlyif' => 'running' 19 | }, 20 | 'when running without onlyif custom command' => { 21 | 'interactive' => true, 22 | 'onlyif' => 'custom' 23 | }, 24 | 'when running without onlyif' => { 25 | 'interactive' => true 26 | }, 27 | 'when running with unless' => { 28 | 'interactive' => true, 29 | 'unless' => 'some_command arg1' 30 | }, 31 | 'when running without unless' => { 32 | 'interactive' => true 33 | }, 34 | 'with title that need sanitisation' => { 35 | 'detach' => true, 36 | 'sanitise_name' => true 37 | }, 38 | 'with environment variables passed to exec' => { 39 | 'env' => [ 40 | 'FOO=BAR', 41 | 'FOO2=BAR2', 42 | ] 43 | } 44 | } 45 | 46 | describe 'docker::exec', type: :define do 47 | on_supported_os.each do |os, os_facts| 48 | ## 49 | ## set some needed facts 50 | ## 51 | facts = if os.include?('windows') 52 | windows_facts.merge(os_facts) 53 | else 54 | os_facts 55 | end 56 | 57 | ## 58 | ## get defaults values from params 59 | ## 60 | defaults = get_defaults(facts) 61 | 62 | context "on #{os}" do 63 | tests.each do |title, local_params| 64 | context title do 65 | params = { 66 | 'command' => '/bin/echo foo', 67 | 'container' => 'some_conainer_name', 68 | 'detach' => false, 69 | 'env' => [], 70 | 'interactive' => false, 71 | 'onlyif' => :undef, 72 | 'refreshonly' => false, 73 | 'sanitise_name' => true, 74 | 'tty' => false, 75 | 'unless' => :undef 76 | }.merge(local_params) 77 | 78 | let(:facts) do 79 | facts 80 | end 81 | 82 | let(:params) do 83 | params 84 | end 85 | 86 | let(:title) do 87 | title 88 | end 89 | 90 | include_examples 'exec', params, facts, defaults 91 | end 92 | end 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /spec/defines/plugin_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'foo/setting:latest' => { 7 | 'settings' => [ 8 | 'VAR1=test', 9 | 'VAR2=value', 10 | ] 11 | }, 12 | 'foo/disabled:latest' => { 13 | 'enabled' => false 14 | }, 15 | 'foo/force_remove:latest' => { 16 | 'ensure' => 'absent', 17 | 'force_remove' => true 18 | } 19 | } 20 | 21 | describe 'docker::plugin', type: :define do 22 | on_supported_os.each do |os, os_facts| 23 | ## 24 | ## set some needed facts 25 | ## 26 | facts = if os.include?('windows') 27 | windows_facts.merge(os_facts) 28 | else 29 | os_facts 30 | end 31 | 32 | ## 33 | ## get defaults values from params 34 | ## 35 | defaults = get_defaults(facts) 36 | 37 | context "on #{os}" do 38 | tests.each do |title, local_params| 39 | context title do 40 | params = { 41 | 'ensure' => 'present', 42 | 'plugin_name' => title, 43 | 'enabled' => true, 44 | 'timeout' => :undef, 45 | 'plugin_alias' => :undef, 46 | 'disable_on_install' => false, 47 | 'disable_content_trust' => true, 48 | 'grant_all_permissions' => true, 49 | 'force_remove' => true, 50 | 'settings' => [] 51 | }.merge(local_params) 52 | 53 | let(:facts) do 54 | facts 55 | end 56 | 57 | let(:params) do 58 | params 59 | end 60 | 61 | let(:title) do 62 | title 63 | end 64 | 65 | if facts[:os]['family'] == 'windows' 66 | it { 67 | expect(subject).to compile.and_raise_error(%r{Feature not implemented on windows.}) 68 | } 69 | 70 | next 71 | end 72 | 73 | include_examples 'plugin', params, facts, defaults 74 | end 75 | end 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /spec/defines/secrets_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'with ensure present' => { 7 | 'secret_name' => 'test_secret', 8 | 'secret_path' => '/root/secret.txt', 9 | 'label' => ['test'] 10 | }, 11 | 'with ensure absent' => { 12 | 'ensure' => 'absent', 13 | 'secret_name' => 'test_secret' 14 | } 15 | } 16 | 17 | describe 'docker::secrets', type: :define do 18 | on_supported_os.each do |os, os_facts| 19 | ## 20 | ## set some needed facts 21 | ## 22 | facts = if os.include?('windows') 23 | windows_facts.merge(os_facts) 24 | else 25 | os_facts 26 | end 27 | 28 | ## 29 | ## get defaults values from params 30 | ## 31 | defaults = get_defaults(facts) 32 | 33 | context "on #{os}" do 34 | tests.each do |title, local_params| 35 | context title do 36 | params = { 37 | 'ensure' => 'present', 38 | 'label' => [], 39 | 'secret_name' => :undef, 40 | 'secret_path' => :undef 41 | }.merge(local_params) 42 | 43 | let(:facts) do 44 | facts 45 | end 46 | 47 | let(:params) do 48 | params 49 | end 50 | 51 | let(:title) do 52 | title 53 | end 54 | 55 | include_examples 'secrets', title, params, facts, defaults 56 | end 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /spec/defines/services_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'with ensure => present and service create' => { 7 | 'create' => true, 8 | 'service_name' => 'foo', 9 | 'image' => 'foo:bar', 10 | 'publish' => '80:80', 11 | 'replicas' => '5', 12 | 'extra_params' => ['--update-delay 1m', '--restart-window 30s'], 13 | 'env' => ['MY_ENV=1', 'MY_ENV2=2'], 14 | 'label' => ['com.example.foo="bar"', 'bar=baz'], 15 | 'mounts' => ['type=bind,src=/tmp/a,dst=/tmp/a', 'type=bind,src=/tmp/b,dst=/tmp/b,readonly'], 16 | 'networks' => ['overlay'], 17 | 'command' => 'echo hello world' 18 | }, 19 | 'multiple services declaration' => { 20 | 'service_name' => 'foo_2', 21 | 'image' => 'foo:bar', 22 | 'command' => ['echo', 'hello', 'world'] 23 | }, 24 | 'multiple publish ports and multiple networks' => { 25 | 'service_name' => 'foo_3', 26 | 'image' => 'foo:bar', 27 | 'publish' => ['80:8080', '9000:9000'], 28 | 'networks' => ['foo_1', 'foo_2'] 29 | }, 30 | 'with ensure => present and service update' => { 31 | 'create' => false, 32 | 'update' => true, 33 | 'service_name' => 'foo', 34 | 'image' => 'bar:latest' 35 | }, 36 | 'with ensure => present and service scale' => { 37 | 'create' => false, 38 | 'scale' => true, 39 | 'service_name' => 'bar', 40 | 'replicas' => '5' 41 | }, 42 | 'with ensure => absent' => { 43 | 'ensure' => 'absent', 44 | 'service_name' => 'foo' 45 | }, 46 | 'when adding a system user' => { 47 | 'user' => ['user1'] 48 | } 49 | } 50 | 51 | describe 'docker::services', type: :define do 52 | on_supported_os.each do |os, os_facts| 53 | ## 54 | ## set some needed facts 55 | ## 56 | facts = if os.include?('windows') 57 | windows_facts.merge(os_facts) 58 | else 59 | os_facts 60 | end 61 | 62 | ## 63 | ## get defaults values from params 64 | ## 65 | defaults = get_defaults(facts) 66 | 67 | context "on #{os}" do 68 | tests.each do |title, local_params| 69 | context title do 70 | params = { 71 | 'ensure' => 'present', 72 | 'create' => true, 73 | 'update' => false, 74 | 'scale' => false, 75 | 'detach' => true, 76 | 'tty' => false, 77 | 'env' => [], 78 | 'label' => [], 79 | 'extra_params' => [], 80 | 'image' => :undef, 81 | 'service_name' => :undef, 82 | 'publish' => :undef, 83 | 'replicas' => :undef, 84 | 'user' => :undef, 85 | 'workdir' => :undef, 86 | 'host_socket' => :undef, 87 | 'registry_mirror' => :undef, 88 | 'mounts' => :undef, 89 | 'networks' => :undef, 90 | 'command' => :undef 91 | }.merge(local_params) 92 | 93 | let(:facts) do 94 | facts 95 | end 96 | 97 | let(:params) do 98 | params 99 | end 100 | 101 | let(:title) do 102 | 'rspec_services' 103 | end 104 | 105 | if params['ensure'] == 'absent' && (params['update'] || params['scale']) 106 | it { 107 | expect(subject).to compile.and_raise_error('When removing a service you can not update it.') 108 | } 109 | 110 | next 111 | end 112 | 113 | include_examples 'services', 'rspec_services', params, facts, defaults 114 | end 115 | end 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /spec/defines/stack_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'create stack with compose file' => { 7 | 'stack_name' => 'foo', 8 | 'compose_files' => ['/tmp/docker-compose.yaml'], 9 | 'resolve_image' => 'always' 10 | }, 11 | 'create stack with multiple compose files' => { 12 | 'stack_name' => 'foo', 13 | 'compose_files' => ['/tmp/docker-compose.yaml', '/tmp/docker-compose-2.yaml'], 14 | 'resolve_image' => 'always' 15 | }, 16 | 'with prune' => { 17 | 'stack_name' => 'foo', 18 | 'compose_files' => ['/tmp/docker-compose.yaml'], 19 | 'prune' => true 20 | }, 21 | 'with ensure => absent' => { 22 | 'ensure' => 'absent', 23 | 'stack_name' => 'foo' 24 | } 25 | } 26 | 27 | describe 'docker::stack', type: :define do 28 | on_supported_os.each do |os, os_facts| 29 | ## 30 | ## set some needed facts 31 | ## 32 | facts = if os.include?('windows') 33 | windows_facts.merge(os_facts) 34 | else 35 | os_facts 36 | end 37 | 38 | ## 39 | ## get defaults values from params 40 | ## 41 | defaults = get_defaults(facts) 42 | 43 | context "on #{os}" do 44 | tests.each do |title, local_params| 45 | context title do 46 | params = { 47 | 'ensure' => 'present', 48 | 'stack_name' => :undef, 49 | 'bundle_file' => :undef, 50 | 'compose_files' => :undef, 51 | 'prune' => false, 52 | 'with_registry_auth' => false, 53 | 'resolve_image' => :undef 54 | }.merge(local_params) 55 | 56 | let(:facts) do 57 | facts 58 | end 59 | 60 | let(:params) do 61 | params 62 | end 63 | 64 | let(:title) do 65 | 'rspec_stack' 66 | end 67 | 68 | include_examples 'stack', 'rspec_stack', params, facts, defaults 69 | end 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/defines/swarm_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | tests = { 6 | 'with ensure => present and swarm init' => { 7 | 'init' => true, 8 | 'advertise_addr' => '192.168.1.1', 9 | 'listen_addr' => '192.168.1.1' 10 | }, 11 | 'with ensure => present and swarm init and default-addr-pool and default_addr_pool_mask_length' => { 12 | 'init' => true, 13 | 'advertise_addr' => '192.168.1.1', 14 | 'listen_addr' => '192.168.1.1', 15 | 'default_addr_pool' => ['30.30.0.0/16', '40.40.0.0/16'], 16 | 'default_addr_pool_mask_length' => '24' 17 | }, 18 | 'with ensure => present and swarm join' => { 19 | 'join' => true, 20 | 'advertise_addr' => '192.168.1.1', 21 | 'listen_addr' => '192.168.1.1', 22 | 'token' => 'foo', 23 | 'manager_ip' => '192.168.1.2' 24 | }, 25 | 'with ensure => absent' => { 26 | 'ensure' => 'absent', 27 | 'join' => true, 28 | 'advertise_addr' => '192.168.1.1', 29 | 'listen_addr' => '192.168.1.1', 30 | 'token' => 'foo', 31 | 'manager_ip' => '192.168.1.2' 32 | } 33 | } 34 | 35 | describe 'docker::swarm', type: :define do 36 | on_supported_os.each do |os, os_facts| 37 | ## 38 | ## set some needed facts 39 | ## 40 | facts = if os.include?('windows') 41 | windows_facts.merge(os_facts) 42 | else 43 | os_facts 44 | end 45 | 46 | ## 47 | ## get defaults values from params 48 | ## 49 | defaults = get_defaults(facts) 50 | 51 | context "on #{os}" do 52 | tests.each do |title, local_params| 53 | context title do 54 | params = { 55 | 'ensure' => 'present', 56 | 'init' => false, 57 | 'join' => false, 58 | 'advertise_addr' => :undef, 59 | 'autolock' => false, 60 | 'cert_expiry' => :undef, 61 | 'default_addr_pool' => :undef, 62 | 'default_addr_pool_mask_length' => :undef, 63 | 'dispatcher_heartbeat' => :undef, 64 | 'external_ca' => :undef, 65 | 'force_new_cluster' => false, 66 | 'listen_addr' => :undef, 67 | 'max_snapshots' => :undef, 68 | 'snapshot_interval' => :undef, 69 | 'token' => :undef, 70 | 'manager_ip' => :undef 71 | }.merge(local_params) 72 | 73 | let(:facts) do 74 | facts 75 | end 76 | 77 | let(:params) do 78 | params 79 | end 80 | 81 | let(:title) do 82 | 'rspec_swarm' 83 | end 84 | 85 | include_examples 'swarm', 'rspec_swarm', params, facts, defaults 86 | end 87 | end 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_network_inspect_bridge: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Name": "bridge", 4 | "Id": "d9e04c239a5353b3ece6f2c9ab4f318aa4e23e52de37df1b8b84897ae5269e40", 5 | "Created": "2017-08-23T11:04:57.365447259-04:00", 6 | "Scope": "local", 7 | "Driver": "bridge", 8 | "EnableIPv6": false, 9 | "IPAM": { 10 | "Driver": "default", 11 | "Options": null, 12 | "Config": [ 13 | { 14 | "Subnet": "172.17.0.0/16", 15 | "Gateway": "172.17.0.1" 16 | } 17 | ] 18 | }, 19 | "Internal": false, 20 | "Attachable": false, 21 | "Containers": {}, 22 | "Options": { 23 | "com.docker.network.bridge.default_bridge": "true", 24 | "com.docker.network.bridge.enable_icc": "true", 25 | "com.docker.network.bridge.enable_ip_masquerade": "true", 26 | "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", 27 | "com.docker.network.bridge.name": "docker0", 28 | "com.docker.network.driver.mtu": "1500" 29 | }, 30 | "Labels": {} 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_network_inspect_dummyapp_default: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Name": "dummyapp_default", 4 | "Id": "c5810f1e3113e8856c0615d9484a7491b7367ea80c6c32a2e5118069fe4af565", 5 | "Created": "2017-11-28T11:37:08.744115226-05:00", 6 | "Scope": "local", 7 | "Driver": "bridge", 8 | "EnableIPv6": false, 9 | "IPAM": { 10 | "Driver": "default", 11 | "Options": null, 12 | "Config": [ 13 | { 14 | "Subnet": "172.18.0.0/16", 15 | "Gateway": "172.18.0.1" 16 | } 17 | ] 18 | }, 19 | "Internal": false, 20 | "Attachable": false, 21 | "Containers": {}, 22 | "Options": {}, 23 | "Labels": {} 24 | } 25 | ] 26 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_network_inspect_host: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Name": "host", 4 | "Id": "ca5f5f36c8d7311d43a5f84147719b5437c8d3a80b502498a543cc279ee348f7", 5 | "Created": "2017-02-16T12:45:25.180741832-05:00", 6 | "Scope": "local", 7 | "Driver": "host", 8 | "EnableIPv6": false, 9 | "IPAM": { 10 | "Driver": "default", 11 | "Options": null, 12 | "Config": [] 13 | }, 14 | "Internal": false, 15 | "Attachable": false, 16 | "Containers": {}, 17 | "Options": {}, 18 | "Labels": {} 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_network_inspect_none: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Name": "none", 4 | "Id": "23d26bed53a8c458e40268f559ce7b5bb40d1a9a090c7acfc931d9fc2c4eb169", 5 | "Created": "2017-02-16T12:45:25.171935752-05:00", 6 | "Scope": "local", 7 | "Driver": "null", 8 | "EnableIPv6": false, 9 | "IPAM": { 10 | "Driver": "default", 11 | "Options": null, 12 | "Config": [] 13 | }, 14 | "Internal": false, 15 | "Attachable": false, 16 | "Containers": {}, 17 | "Options": {}, 18 | "Labels": {} 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_network_list: -------------------------------------------------------------------------------- 1 | d9e04c239a53 bridge bridge local 2 | ca5f5f36c8d7 host host local 3 | 23d26bed53a8 none null local 4 | c5810f1e3113 dummyapp_default bridge local 5 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_swarm_manager_token: -------------------------------------------------------------------------------- 1 | SWMTKN-1-2m7ekt7511j5kgrc6seyrewpdxv47ksz1sdg7iybzhuug6nmws-8gh1ns1lcavgau8k9p6ou7xj3 2 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_swarm_worker_token: -------------------------------------------------------------------------------- 1 | SWMTKN-1-2m7ekt7511j5kgrc6seyrewpdxv47ksz1sdg7iybzhuug6nmws-0jh0syqeoj3tlr81p165ydfkm 2 | -------------------------------------------------------------------------------- /spec/fixtures/facts/docker_version: -------------------------------------------------------------------------------- 1 | { 2 | "Client": { 3 | "ApiVersion": "1.27", 4 | "Arch": "amd64", 5 | "BuildTime": "Fri Mar 24 00:40:33 2017", 6 | "GitCommit": "c6d412e", 7 | "GoVersion": "go1.7.5", 8 | "Os": "linux", 9 | "Version": "17.03.1-ce-client" 10 | }, 11 | "Server": { 12 | "ApiVersion": "1.27", 13 | "Arch": "amd64", 14 | "BuildTime": "Fri Mar 24 00:40:33 2017", 15 | "GitCommit": "c6d412e", 16 | "GoVersion": "go1.7.5", 17 | "KernelVersion": "3.13.0-115-generic", 18 | "MinAPIVersion": "1.12", 19 | "Os": "linux", 20 | "Version": "17.03.1-ce-server" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spec/fixtures/facts/facts_with_compose: -------------------------------------------------------------------------------- 1 | {"network" => {"managed_interfaces"=>{"br-c5810f1e3113"=>"dummyapp_default"}, "bridge"=>{"Name"=>"bridge", "Id"=>"d9e04c239a5353b3ece6f2c9ab4f318aa4e23e52de37df1b8b84897ae5269e40", "Created"=>"2017-08-23T11:04:57.365447259-04:00", "Scope"=>"local", "Driver"=>"bridge", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[{"Subnet"=>"172.17.0.0/16", "Gateway"=>"172.17.0.1"}]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{"com.docker.network.bridge.default_bridge"=>"true", "com.docker.network.bridge.enable_icc"=>"true", "com.docker.network.bridge.enable_ip_masquerade"=>"true", "com.docker.network.bridge.host_binding_ipv4"=>"0.0.0.0", "com.docker.network.bridge.name"=>"docker0", "com.docker.network.driver.mtu"=>"1500"}, "Labels"=>{}}, "host"=>{"Name"=>"host", "Id"=>"ca5f5f36c8d7311d43a5f84147719b5437c8d3a80b502498a543cc279ee348f7", "Created"=>"2017-02-16T12:45:25.180741832-05:00", "Scope"=>"local", "Driver"=>"host", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}, "none"=>{"Name"=>"none", "Id"=>"23d26bed53a8c458e40268f559ce7b5bb40d1a9a090c7acfc931d9fc2c4eb169", "Created"=>"2017-02-16T12:45:25.171935752-05:00", "Scope"=>"local", "Driver"=>"null", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}, "dummyapp_default"=>{"Name"=>"dummyapp_default", "Id"=>"c5810f1e3113e8856c0615d9484a7491b7367ea80c6c32a2e5118069fe4af565", "Created"=>"2017-11-28T11:37:08.744115226-05:00", "Scope"=>"local", "Driver"=>"bridge", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[{"Subnet"=>"172.18.0.0/16", "Gateway"=>"172.18.0.1"}]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}}} 2 | -------------------------------------------------------------------------------- /spec/fixtures/facts/facts_without_compose: -------------------------------------------------------------------------------- 1 | {"network" => {"managed_interfaces"=>{}, "bridge"=>{"Name"=>"bridge", "Id"=>"d9e04c239a5353b3ece6f2c9ab4f318aa4e23e52de37df1b8b84897ae5269e40", "Created"=>"2017-08-23T11:04:57.365447259-04:00", "Scope"=>"local", "Driver"=>"bridge", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[{"Subnet"=>"172.17.0.0/16", "Gateway"=>"172.17.0.1"}]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{"com.docker.network.bridge.default_bridge"=>"true", "com.docker.network.bridge.enable_icc"=>"true", "com.docker.network.bridge.enable_ip_masquerade"=>"true", "com.docker.network.bridge.host_binding_ipv4"=>"0.0.0.0", "com.docker.network.bridge.name"=>"docker0", "com.docker.network.driver.mtu"=>"1500"}, "Labels"=>{}}, "host"=>{"Name"=>"host", "Id"=>"ca5f5f36c8d7311d43a5f84147719b5437c8d3a80b502498a543cc279ee348f7", "Created"=>"2017-02-16T12:45:25.180741832-05:00", "Scope"=>"local", "Driver"=>"host", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}, "none"=>{"Name"=>"none", "Id"=>"23d26bed53a8c458e40268f559ce7b5bb40d1a9a090c7acfc931d9fc2c4eb169", "Created"=>"2017-02-16T12:45:25.171935752-05:00", "Scope"=>"local", "Driver"=>"null", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}, "dummyapp_default"=>{"Name"=>"dummyapp_default", "Id"=>"c5810f1e3113e8856c0615d9484a7491b7367ea80c6c32a2e5118069fe4af565", "Created"=>"2017-11-28T11:37:08.744115226-05:00", "Scope"=>"local", "Driver"=>"bridge", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>[{"Subnet"=>"172.18.0.0/16", "Gateway"=>"172.18.0.1"}]}, "Internal"=>false, "Attachable"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}}} 2 | -------------------------------------------------------------------------------- /spec/fixtures/facts/processors: -------------------------------------------------------------------------------- 1 | { 2 | "count": 8, 3 | "isa": "i386", 4 | "models": [ 5 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 6 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 7 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 8 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 9 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 10 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 11 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz", 12 | "Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz" 13 | ], 14 | "physicalcount": 4, 15 | "speed": "2.70 GHz" 16 | } -------------------------------------------------------------------------------- /spec/functions/env_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'docker::env' do 6 | it { is_expected.to run.with_params([4]).and_return([4]) } 7 | it { is_expected.to run.with_params([4, 5, '3']).and_return([4, 5, '3']) } 8 | it { is_expected.to run.with_params(2).and_raise_error(StandardError) } 9 | it { is_expected.to run.with_params('string').and_raise_error(StandardError) } 10 | it { is_expected.to run.with_params(nil).and_raise_error(StandardError) } 11 | end 12 | -------------------------------------------------------------------------------- /spec/helper/get_docker_exec_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_exec_flags(args) 4 | flags = [] 5 | 6 | flags << '--detach=true' if args['detach'] 7 | 8 | flags << '--interactive=true' if args['interactive'] 9 | 10 | flags << '--tty=true' if args['tty'] 11 | 12 | unless args['env'].empty? 13 | args['env'].each do |namevaluepair| 14 | flags << "--env #{namevaluepair}" 15 | end 16 | end 17 | 18 | flags.flatten.join(' ') 19 | end 20 | -------------------------------------------------------------------------------- /spec/helper/get_docker_plugin_enable_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_plugin_enable_flags(args) 4 | flags = [] 5 | 6 | flags << '--force' if args['force_remove'] == true 7 | if args['plugin_alias'] && args['plugin_alias'].to_s != 'undef' 8 | flags << "'#{args['plugin_alias']}'" 9 | elsif args['plugin_name'] && args['plugin_name'].to_s != 'undef' 10 | flags << "'#{args['plugin_name']}'" 11 | end 12 | 13 | flags.flatten.join(' ') 14 | end 15 | -------------------------------------------------------------------------------- /spec/helper/get_docker_plugin_install_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_plugin_install_flags(args) 4 | flags = [] 5 | flags << "--alias #{args['plugin_alias']}" if args['plugin_alias'] && args['plugin_alias'].to_s != 'undef' 6 | flags << '--disable' if args['disable_on_install'] == true 7 | flags << '--disable-content-trust' if args['disable_content_trust'] == true 8 | flags << '--grant-all-permissions' if args['grant_all_permissions'] == true 9 | flags << "'#{args['plugin_name']}'" if args['plugin_name'] && args['plugin_name'].to_s != 'undef' 10 | 11 | if args['settings'].is_a? Array 12 | args['settings'].each do |setting| 13 | flags << setting.to_s 14 | end 15 | end 16 | 17 | flags.flatten.join(' ') 18 | end 19 | -------------------------------------------------------------------------------- /spec/helper/get_docker_plugin_remove_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_plugin_remove_flags(args) 4 | flags = [] 5 | 6 | flags << '--force' if args['force_remove'] == true 7 | flags << "'#{args['plugin_name']}'" if args['plugin_name'] && args['plugin_name'].to_s != 'undef' 8 | 9 | flags.flatten.join(' ') 10 | end 11 | -------------------------------------------------------------------------------- /spec/helper/get_docker_run_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | 5 | def get_docker_run_flags(args) 6 | flags = [] 7 | 8 | flags << "-u '#{args['username'].shellescape}'" if args['username'] 9 | 10 | flags << "-h '#{args['hostname'].shellescape}'" if args['hostname'] 11 | 12 | flags << "--restart '#{args['restart']}'" if args['restart'] 13 | 14 | flags << "--net #{args['net']}" if args['net'].is_a? String 15 | 16 | flags << "-m #{args['memory_limit']}" if args['memory_limit'] 17 | 18 | cpusets = [args['cpuset']].flatten.compact 19 | 20 | unless cpusets.empty? 21 | value = cpusets.join(',') 22 | flags << "--cpuset-cpus=#{value}" 23 | end 24 | 25 | flags << '-n false' if args['disable_network'] 26 | 27 | flags << '--privileged' if args['privileged'] 28 | 29 | flags << "--health-cmd='#{args['health_check_cmd']}'" if args['health_check_cmd'] && args['health_check_cmd'].to_s != 'undef' 30 | 31 | flags << "--health-interval=#{args['health_check_interval']}s" if args['health_check_interval'] && args['health_check_interval'].to_s != 'undef' 32 | 33 | flags << '-t' if args['tty'] 34 | 35 | flags << '--read-only=true' if args['read_only'] 36 | 37 | params_join_char = if args['osfamily'] && args['osfamily'].to_s != 'undef' 38 | args['osfamily'].casecmp('windows').zero? ? " `\n" : " \\\n" 39 | else 40 | " \\\n" 41 | end 42 | 43 | multi_flags = ->(values, fmt) { 44 | filtered = [values].flatten.compact 45 | filtered.map { |val| (fmt + params_join_char) % val } 46 | } 47 | 48 | [ 49 | ['--dns %s', 'dns'], 50 | ['--dns-search %s', 'dns_search'], 51 | ['--expose=%s', 'expose'], 52 | ['--link %s', 'links'], 53 | ['--lxc-conf="%s"', 'lxc_conf'], 54 | ['--volumes-from %s', 'volumes_from'], 55 | ['-e "%s"', 'env'], 56 | ['--env-file %s', 'env_file'], 57 | ['-p %s', 'ports'], 58 | ['-l %s', 'labels'], 59 | ['--add-host %s', 'hostentries'], 60 | ['-v %s', 'volumes'], 61 | ].each do |format, key| 62 | values = args[key] 63 | new_flags = multi_flags.call(values, format) 64 | flags << new_flags 65 | end 66 | 67 | args['extra_params'].each do |param| 68 | flags << param if args['param'].to_s != 'undef' 69 | end 70 | 71 | # Some software (inc systemd) will truncate very long lines using glibc's 72 | # max line length. Wrap options across multiple lines with '\' to avoid 73 | flags.flatten.reject { |val| val.to_s == 'undef' }.join(params_join_char) 74 | end 75 | -------------------------------------------------------------------------------- /spec/helper/get_docker_secrets_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | 5 | def get_docker_secrets_flags(args) 6 | flags = [] 7 | 8 | flags << 'create' if args['ensure'].to_s == 'present' 9 | 10 | flags << "'#{args['secret_name']}'" if args['secret_name'] && args['secret_name'].to_s != 'undef' 11 | 12 | flags << "'#{args['secret_path']}'" if args['secret_path'] && args['secret_path'].to_s != 'undef' 13 | 14 | multi_flags = ->(values, format) { 15 | filtered = [values].flatten.compact 16 | filtered.map { |val| format + (" \\\n" % val) } 17 | } 18 | [ 19 | ['-l %s', 'label'], 20 | ].each do |(format, key)| 21 | values = args[key] 22 | new_flags = multi_flags.call(values, format) 23 | flags.concat(new_flags) 24 | end 25 | 26 | flags.flatten.join(' ') 27 | end 28 | -------------------------------------------------------------------------------- /spec/helper/get_docker_service_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | 5 | def get_docker_service_flags(args) 6 | flags = [] 7 | 8 | flags << "'#{args['service_name']}'" if args['service_name'] && args['service_name'].to_s != 'undef' 9 | 10 | flags << '--detach' if args['detach'].to_s != 'false' 11 | 12 | if args['env'].is_a? Array 13 | args['env'].each do |env| 14 | flags << "--env '#{env}'" 15 | end 16 | end 17 | 18 | if args['label'].is_a? Array 19 | args['label'].each do |label| 20 | flags << "--label #{label}" 21 | end 22 | end 23 | 24 | if args['mounts'].is_a? Array 25 | args['mounts'].each do |mount| 26 | flags << "--mount #{mount}" 27 | end 28 | end 29 | 30 | if args['networks'].is_a? Array 31 | args['networks'].each do |network| 32 | flags << "--network #{network}" 33 | end 34 | end 35 | 36 | if args['publish'].is_a? Array 37 | args['publish'].each do |port| 38 | flags << "--publish #{port}" 39 | end 40 | elsif args['publish'] && args['publish'].to_s != 'undef' 41 | flags << "--publish '#{args['publish']}'" 42 | end 43 | 44 | flags << "--replicas '#{args['replicas']}'" if args['replicas'] && args['replicas'].to_s != 'undef' 45 | 46 | flags << '--tty' if args['tty'].to_s != 'false' 47 | 48 | flags << "--user '#{args['user']}'" if args['user'] && args['user'].to_s != 'undef' 49 | 50 | flags << "--workdir '#{args['workdir']}'" if args['workdir'] && args['workdir'].to_s != 'undef' 51 | 52 | if args['extra_params'].is_a? Array 53 | args['extra_params'].each do |param| 54 | flags << param 55 | end 56 | end 57 | 58 | flags << "-H '#{args['host_socket']}'" if args['host_socket'] && args['host_socket'].to_s != 'undef' 59 | 60 | if args['registry_mirror'].is_a? Array 61 | args['registry_mirror'].each do |param| 62 | flags << "--registry-mirror='#{param}'" 63 | end 64 | elsif args['registry_mirror'] && args['registry_mirror'].to_s != 'undef' 65 | flags << "--registry-mirror='#{args['registry_mirror']}'" 66 | end 67 | 68 | flags << "'#{args['image']}'" if args['image'] && args['image'].to_s != 'undef' 69 | 70 | if args['command'].is_a? Array 71 | flags << args['command'].join(' ') 72 | elsif args['command'] && args['command'].to_s != 'undef' 73 | flags << args['command'].to_s 74 | end 75 | 76 | flags.flatten.join(' ') 77 | end 78 | -------------------------------------------------------------------------------- /spec/helper/get_docker_stack_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_stack_flags(args) 4 | flags = [] 5 | 6 | flags << "--bundle-file '#{args['bundle_file']}'" if args['bundle_file'] && args['bundle_file'].to_s != 'undef' 7 | 8 | if args['compose_files'] && args['compose_files'].to_s != 'undef' 9 | args['compose_files'].each do |file| 10 | flags << "--compose-file '#{file}'" 11 | end 12 | end 13 | 14 | flags << "--resolve-image '#{args['resolve_image']}'" if args['resolve_image'] && args['resolve_image'].to_s != 'undef' 15 | 16 | flags << '--prune' if args['prune'] && args['prune'].to_s != 'undef' 17 | 18 | flags << '--with-registry-auth' if args['with_registry_auth'] && args['with_registry_auth'].to_s != 'undef' 19 | 20 | flags.flatten.join(' ') 21 | end 22 | -------------------------------------------------------------------------------- /spec/helper/get_docker_swarm_init_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_swarm_init_flags(args) 4 | flags = [] 5 | 6 | flags << 'init' if args['init'].to_s != 'false' 7 | 8 | flags << "--advertise-addr '#{args['advertise_addr']}'" if args['advertise_addr'] && args['advertise_addr'].to_s != 'undef' 9 | 10 | flags << '--autolock' if args['autolock'].to_s != 'false' 11 | 12 | flags << "--cert-expiry '#{args['cert_expiry']}'" if args['cert_expiry'] && args['cert_expiry'].to_s != 'undef' 13 | 14 | if args['default_addr_pool'].is_a? Array 15 | args['default_addr_pool'].each do |default_addr_pool| 16 | flags << "--default-addr-pool #{default_addr_pool}" 17 | end 18 | end 19 | 20 | flags << "--default-addr-pool-mask-length '#{args['default_addr_pool_mask_length']}'" if args['default_addr_pool_mask_length'] && args['default_addr_pool_mask_length'].to_s != 'undef' 21 | 22 | flags << "--dispatcher-heartbeat '#{args['dispatcher_heartbeat']}'" if args['dispatcher_heartbeat'] && args['dispatcher_heartbeat'].to_s != 'undef' 23 | 24 | flags << "--external-ca '#{args['external_ca']}'" if args['external_ca'] && args['external_ca'].to_s != 'undef' 25 | 26 | flags << '--force-new-cluster' if args['force_new_cluster'].to_s != 'false' 27 | 28 | flags << "--listen-addr '#{args['listen_addr']}'" if args['listen_addr'] && args['listen_addr'].to_s != 'undef' 29 | 30 | flags << "--max-snapshots '#{args['max_snapshots']}'" if args['max_snapshots'] && args['max_snapshots'].to_s != 'undef' 31 | 32 | flags << "--snapshot-interval '#{args['snapshot_interval']}'" if args['snapshot_interval'] && args['snapshot_interval'].to_s != 'undef' 33 | 34 | flags.flatten.join(' ') 35 | end 36 | -------------------------------------------------------------------------------- /spec/helper/get_docker_swarm_join_flags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_docker_swarm_join_flags(args) 4 | flags = [] 5 | 6 | flags << 'join' if args['join'].to_s != 'false' 7 | 8 | flags << "--advertise-addr '#{args['advertise_addr']}'" if args['advertise_addr'] && args['advertise_addr'].to_s != 'undef' 9 | 10 | flags << "--listen-addr \"#{args['listen_addr']}\"" if args['listen_addr'] && args['listen_addr'].to_s != 'undef' 11 | 12 | flags << "--token '#{args['token']}'" if args['token'] && args['token'].to_s != 'undef' 13 | 14 | flags.flatten.join(' ') 15 | end 16 | -------------------------------------------------------------------------------- /spec/helper/get_values_init.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def get_values_init(_params, _facts) 4 | if _params['version'] == :undef || _params['version'] !~ %r{^(17[.][0-1][0-9][.][0-1](~|-|\.)ce|1.\d+)} 5 | if _params['docker_ee'] 6 | package_location = _params['docker_ee_source_location'] 7 | package_key_source = _params['docker_ee_key_source'] 8 | package_key_check_source = true 9 | package_key = _params['docker_ee_key_id'] 10 | package_repos = _params['docker_ee_repos'] 11 | release = _params['docker_ee_release'] 12 | docker_start_command = _params['docker_ee_start_command'] 13 | docker_package_name = _params['docker_ee_package_name'] 14 | else 15 | case _facts[:os]['family'] 16 | when 'Debian' 17 | package_location = _params['docker_ce_source_location'] 18 | package_key_source = _params['docker_ce_key_source'] 19 | package_key = _params['docker_ce_key_id'] 20 | package_repos = _params['docker_ce_channel'] 21 | release = _params['docker_ce_release'] 22 | when 'RedHat' 23 | package_location = _params['docker_ce_source_location'] 24 | package_key_source = _params['docker_ce_key_source'] 25 | package_key_check_source = true 26 | # when 'windows' 27 | # fail('This module only work for Docker Enterprise Edition on Windows.') 28 | else 29 | package_location = _params['docker_package_location'] 30 | package_key_source = _params['docker_package_key_source'] 31 | package_key_check_source = _params['docker_package_key_check_source'] 32 | end 33 | 34 | docker_start_command = _params['docker_ce_start_command'] 35 | docker_package_name = _params['docker_ce_package_name'] 36 | end 37 | else 38 | package_location = _params['docker_package_location'] 39 | package_key_source = _params['docker_package_key_source'] 40 | package_key_check_source = _params['docker_package_key_check_source'] 41 | case _facts[:os]['family'] 42 | when 'Debian' 43 | package_key = _params['docker_package_key_id'] 44 | package_repos = 'main' 45 | release = _params['docker_package_release'] 46 | end 47 | 48 | docker_start_command = _params['docker_engine_start_command'] 49 | docker_package_name = _params['docker_engine_package_name'] 50 | end 51 | 52 | root_dir_flag = if _params['version'] != :undef && _params['version'] =~ %r{^(17[.]0[0-4]|1.\d+)} 53 | '-g' 54 | else 55 | '--data-root' 56 | end 57 | 58 | { 59 | 'docker_package_name' => docker_package_name, 60 | 'docker_start_command' => docker_start_command, 61 | 'package_key' => package_key, 62 | 'package_key_check_source' => package_key_check_source, 63 | 'package_key_source' => package_key_source, 64 | 'package_location' => package_location, 65 | 'package_repos' => package_repos, 66 | 'release' => release, 67 | 'root_dir_flag' => root_dir_flag 68 | } 69 | end 70 | -------------------------------------------------------------------------------- /spec/helper/pw_hash.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def pw_hash(_foo, _bar, _asdf) 4 | '$6$foobar$v8j5roVj0D8t.Ipwvk0RrMHiZfZRoBMeVQDywxUKFtdRI2EFRi2X6tbOigjpOsa9UDVzgIBtcl2ZEGcM.jnZZ.' 5 | end 6 | -------------------------------------------------------------------------------- /spec/helper/windows_facts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def windows_facts 4 | { 5 | 'docker_program_data_path' => 'C:/ProgramData', 6 | 'docker_program_files_path' => 'C:/Program Files', 7 | 'docker_systemroot' => 'C:/Windows', 8 | 'docker_user_temp_path' => 'C:/Users/Administrator/AppData/Local/Temp' 9 | } 10 | end 11 | -------------------------------------------------------------------------------- /spec/shared_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'helper/get_defaults' 4 | require 'helper/get_docker_exec_flags' 5 | require 'helper/get_docker_plugin_enable_flags' 6 | require 'helper/get_docker_plugin_install_flags' 7 | require 'helper/get_docker_plugin_remove_flags' 8 | require 'helper/get_docker_run_flags' 9 | require 'helper/get_docker_secrets_flags' 10 | require 'helper/get_docker_service_flags' 11 | require 'helper/get_docker_stack_flags' 12 | require 'helper/get_docker_swarm_init_flags' 13 | require 'helper/get_docker_swarm_join_flags' 14 | require 'helper/get_docker_params_changed' 15 | require 'helper/get_values_init' 16 | require 'helper/pw_hash' 17 | require 'helper/windows_facts' 18 | 19 | require 'shared_examples/compose' 20 | require 'shared_examples/config' 21 | require 'shared_examples/exec' 22 | require 'shared_examples/image' 23 | require 'shared_examples/install' 24 | require 'shared_examples/machine' 25 | require 'shared_examples/params' 26 | require 'shared_examples/plugin' 27 | require 'shared_examples/registry' 28 | require 'shared_examples/repos' 29 | require 'shared_examples/run' 30 | require 'shared_examples/secrets' 31 | require 'shared_examples/service' 32 | require 'shared_examples/services' 33 | require 'shared_examples/stack' 34 | require 'shared_examples/swarm' 35 | require 'shared_examples/system_user' 36 | -------------------------------------------------------------------------------- /spec/shared_examples/compose.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'compose' do |_params, _facts| 4 | ensure_value = _params['ensure'] 5 | version = _params['version'] 6 | 7 | if _params['manage_package'] 8 | ensure_value = 9 | if _params['version'] != :undef && _params['ensure'] != 'absent' 10 | _params['version'] 11 | else 12 | _params['ensure'] 13 | end 14 | 15 | case _facts['os']['family'] 16 | when 'Debian', 'RedHat' 17 | it { 18 | expect(subject).to contain_package('docker-compose-plugin').with( 19 | ensure: ensure_value, 20 | ) 21 | } 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/shared_examples/config.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'config' do |_params, _facts| 4 | docker_users = _params['docker_users'] 5 | 6 | it { 7 | expect(subject).to contain_class('docker::config') 8 | } 9 | 10 | unless docker_users.empty? 11 | docker_users.each do |user| 12 | if _facts[:os]['family'].include?('windows') 13 | it { 14 | expect(subject).to contain_docker__windows_account(user) 15 | } 16 | else 17 | it { 18 | expect(subject).to contain_docker__system_user(user) 19 | } 20 | 21 | include_examples 'system_user', user, _params['docker_group'] 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/shared_examples/exec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'exec' do |_params, _facts, _defaults| 4 | command = _params['command'] 5 | container = _params['container'] 6 | detach = _params['detach'] 7 | docker_command = _defaults['docker_command'] 8 | env = _params['env'] 9 | interactive = _params['interactive'] 10 | onlyif = _params['onlyif'] 11 | refreshonly = _params['refreshonly'] 12 | sanitise_name = _params['sanitise_name'] 13 | tty = _params['tty'] 14 | unless_value = _params['unless'] 15 | 16 | if _facts[:os]['family'] == 'windows' 17 | exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" 18 | exec_timeout = 3000 19 | exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] 20 | exec_provider = 'powershell' 21 | else 22 | exec_environment = 'HOME=/root' 23 | exec_path = ['/bin', '/usr/bin'] 24 | exec_timeout = 0 25 | exec_provider = nil 26 | end 27 | 28 | docker_exec_flags = get_docker_exec_flags( 29 | 'detach' => detach, 30 | 'interactive' => interactive, 31 | 'tty' => tty, 32 | 'env' => env, 33 | ) 34 | 35 | sanitised_container = if sanitise_name 36 | container.gsub('[^0-9A-Za-z.\-_]', '-') 37 | else 38 | container 39 | end 40 | 41 | exec = "#{docker_command} exec #{docker_exec_flags} #{sanitised_container} #{command}" 42 | 43 | unless_command = case unless_value 44 | when :undef, '' 45 | nil 46 | else 47 | "#{docker_command} exec #{docker_exec_flags} #{sanitised_container} #{unless_value}" 48 | end 49 | 50 | onlyif_command = case onlyif 51 | when :undef, '' 52 | nil 53 | when 'running' 54 | "#{docker_command} ps --no-trunc --format='table {{.Names}}' | grep '^#{sanitised_container}$'" 55 | else 56 | onlyif 57 | end 58 | 59 | it { 60 | expect(subject).to contain_exec(exec).with( 61 | 'environment' => exec_environment, 62 | 'onlyif' => onlyif_command, 63 | 'path' => exec_path, 64 | 'refreshonly' => refreshonly, 65 | 'timeout' => exec_timeout, 66 | 'provider' => exec_provider, 67 | 'unless' => unless_command, 68 | ) 69 | } 70 | end 71 | -------------------------------------------------------------------------------- /spec/shared_examples/machine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'machine' do |_params, _facts, _defaults| 4 | ensure_value = _params['ensure'] 5 | version = _params['version'] 6 | install_path = _params['install_path'] 7 | proxy = _params['proxy'] 8 | url = _params['url'] 9 | curl_ensure = _params['curl_ensure'] 10 | 11 | if _facts[:os]['family'] == 'windows' 12 | file_extension = '.exe' 13 | file_owner = 'Administrator' 14 | else 15 | file_extension = '' 16 | file_owner = 'root' 17 | end 18 | 19 | docker_machine_location = "#{install_path}/docker-machine#{file_extension}" 20 | docker_machine_location_versioned = "#{install_path}/docker-machine-#{version}#{file_extension}" 21 | 22 | if ensure_value == 'present' 23 | docker_machine_url = case url 24 | when :undef 25 | "https://github.com/docker/machine/releases/download/v#{version}/docker-machine-#{_facts[:kernel]}-x86_64#{file_extension}" 26 | else 27 | url 28 | end 29 | 30 | proxy_opt = case proxy 31 | when :undef 32 | '' 33 | else 34 | "--proxy #{proxy}" 35 | end 36 | 37 | if _facts[:os]['family'] == 'windows' 38 | docker_download_command = "if (Invoke-WebRequest #{docker_machine_url} #{proxy_opt} -UseBasicParsing -OutFile \"#{docker_machine_location_versioned}\") { exit 0 } else { exit 1 }" 39 | 40 | it { 41 | expect(subject).to contain_exec("Install Docker Machine #{version}").with( 42 | 'provider' => 'powershell', 43 | 'creates' => docker_machine_location_versioned, 44 | ) 45 | 46 | expect(subject).to contain_file(docker_machine_location).with( 47 | 'ensure' => 'link', 48 | 'target' => docker_machine_location_versioned, 49 | ).that_requires( 50 | "Exec[Install Docker Machine #{version}]", 51 | ) 52 | } 53 | else 54 | if curl_ensure 55 | it { 56 | expect(subject).to contain_package('curl') 57 | } 58 | end 59 | 60 | it { 61 | expect(subject).to contain_exec("Install Docker Machine #{version}").with( 62 | 'path' => '/usr/bin/', 63 | 'cwd' => '/tmp', 64 | 'command' => "curl -s -S -L #{proxy_opt} #{docker_machine_url} -o #{docker_machine_location_versioned}", 65 | 'creates' => docker_machine_location_versioned, 66 | ).that_requires( 67 | 'Package[curl]', 68 | ) 69 | 70 | expect(subject).to contain_file(docker_machine_location_versioned).with( 71 | 'owner' => file_owner, 72 | 'mode' => '0755', 73 | ).that_requires( 74 | "Exec[Install Docker Machine #{version}]", 75 | ) 76 | 77 | expect(subject).to contain_file(docker_machine_location).with( 78 | 'ensure' => 'link', 79 | 'target' => docker_machine_location_versioned, 80 | ).that_requires( 81 | "File[#{docker_machine_location_versioned}]", 82 | ) 83 | } 84 | end 85 | else 86 | expect(subject).to contain_file(docker_machine_location_versioned).with( 87 | 'ensure' => 'absent', 88 | ) 89 | 90 | expect(subject).to contain_file(docker_machine_location).with( 91 | 'ensure' => 'absent', 92 | ) 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /spec/shared_examples/params.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'params' do |_facts| 4 | case _facts[:os]['family'] 5 | when 'Debian' 6 | it { 7 | expect(subject).to contain_class('docker::params') 8 | expect(subject).to contain_class('docker::systemd_reload') 9 | expect(subject).to contain_exec('docker-systemd-reload').with( 10 | 'path' => [ 11 | '/bin/', 12 | '/sbin/', 13 | '/usr/bin/', 14 | '/usr/sbin/', 15 | ], 16 | 'command' => 'systemctl daemon-reload', 17 | 'refreshonly' => 'true', 18 | ) 19 | } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/shared_examples/plugin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'plugin' do |_params, _facts, _defaults| 4 | ensure_value = _params['ensure'] 5 | plugin_name = _params['plugin_name'] 6 | enabled = _params['enabled'] 7 | timeout = _params['timeout'] 8 | plugin_alias = _params['plugin_alias'] 9 | disable_on_install = _params['disable_on_install'] 10 | disable_content_trust = _params['disable_content_trust'] 11 | grant_all_permissions = _params['grant_all_permissions'] 12 | force_remove = _params['force_remove'] 13 | settings = _params['settings'] 14 | 15 | docker_command = "#{_defaults['docker_command']} plugin" 16 | 17 | if ensure_value == 'present' 18 | docker_plugin_install_flags = get_docker_plugin_install_flags( 19 | 'plugin_name' => plugin_name, 20 | 'plugin_alias' => plugin_alias, 21 | 'disable_on_install' => disable_on_install, 22 | 'disable_content_trust' => disable_content_trust, 23 | 'grant_all_permissions' => grant_all_permissions, 24 | 'settings' => settings, 25 | ) 26 | 27 | exec_install = "#{docker_command} install #{docker_plugin_install_flags}" 28 | unless_install = "#{docker_command} ls --format='{{.PluginReference}}' | grep -w #{plugin_name}" 29 | 30 | it { 31 | expect(subject).to contain_exec("plugin install #{plugin_name}").with( 32 | 'command' => exec_install, 33 | 'environment' => 'HOME=/root', 34 | 'path' => ['/bin', '/usr/bin'], 35 | 'timeout' => 0, 36 | 'unless' => unless_install, 37 | ) 38 | } 39 | 40 | elsif ensure_value == 'absent' 41 | docker_plugin_remove_flags = get_docker_plugin_remove_flags( 42 | 'plugin_name' => plugin_name, 43 | 'force_remove' => force_remove, 44 | ) 45 | 46 | exec_rm = "#{docker_command} rm #{docker_plugin_remove_flags}" 47 | onlyif_rm = "#{docker_command} ls --format='{{.PluginReference}}' | grep -w #{plugin_name}" 48 | 49 | it { 50 | expect(subject).to contain_exec("plugin remove #{plugin_name}").with( 51 | 'command' => exec_rm, 52 | 'environment' => 'HOME=/root', 53 | 'path' => ['/bin', '/usr/bin'], 54 | 'timeout' => 0, 55 | 'onlyif' => onlyif_rm, 56 | ) 57 | } 58 | end 59 | 60 | if enabled 61 | docker_plugin_enable_flags = get_docker_plugin_enable_flags( 62 | 'plugin_name' => plugin_name, 63 | 'plugin_alias' => plugin_alias, 64 | 'timeout' => timeout, 65 | ) 66 | 67 | exec_enable = "#{docker_command} enable #{docker_plugin_enable_flags}" 68 | onlyif_enable = "#{docker_command} ls -f enabled=false --format='{{.PluginReference}}' | grep -w #{plugin_name}" 69 | 70 | it { 71 | expect(subject).to contain_exec("plugin enable #{plugin_name}").with( 72 | 'command' => exec_enable, 73 | 'environment' => 'HOME=/root', 74 | 'path' => ['/bin', '/usr/bin'], 75 | 'timeout' => 0, 76 | 'onlyif' => onlyif_enable, 77 | ) 78 | } 79 | else 80 | it { 81 | expect(subject).to contain_exec("disable #{plugin_name}").with( 82 | 'command' => "#{docker_command} disable #{plugin_name}", 83 | 'environment' => 'HOME=/root', 84 | 'path' => ['/bin', '/usr/bin'], 85 | 'timeout' => 0, 86 | 'unless' => "#{docker_command} ls -f enabled=false --format='{{.PluginReference}}' | grep -w #{plugin_name}", 87 | ) 88 | } 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/shared_examples/repos.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'repos' do |params, facts| 4 | it { 5 | expect(subject).to contain_class('docker::repos') 6 | } 7 | 8 | values = get_values_init(params, facts) 9 | 10 | location = values['package_location'] 11 | key_source = values['package_key_source'] 12 | key_check_source = values['package_key_check_source'] 13 | architecture = facts[:os]['architecture'] 14 | 15 | unless params['prerequired_packages'].empty? 16 | params['prerequired_packages'].each do |package| 17 | it { 18 | expect(subject).to contain_package(package) 19 | } 20 | end 21 | end 22 | 23 | case facts[:os]['family'] 24 | when 'Debian' 25 | release = values['release'] 26 | package_key = values['package_key'] 27 | package_repos = values['package_repos'] 28 | 29 | if params['use_upstream_package_source'] 30 | it { 31 | expect(subject).to contain_apt__source('docker').with( 32 | 'location' => location, 33 | 'architecture' => architecture, 34 | 'release' => release, 35 | 'repos' => package_repos, 36 | 'key' => { 37 | 'id' => package_key, 38 | 'source' => key_source 39 | }, 40 | 'include' => { 41 | 'src' => false 42 | }, 43 | ) 44 | } 45 | 46 | url_split = location.split('/') 47 | repo_host = url_split[2] 48 | pin_ensure = case params['pin_upstream_package_source'] 49 | when true 50 | 'present' 51 | else 52 | 'absent' 53 | end 54 | 55 | it { 56 | expect(subject).to contain_apt__pin('docker').with( 57 | 'ensure' => pin_ensure, 58 | 'origin' => repo_host, 59 | 'priority' => params['apt_source_pin_level'], 60 | ) 61 | } 62 | 63 | if params['manage_package'] 64 | it { 65 | expect(subject).to contain_class('apt') 66 | } 67 | 68 | if facts[:os]['name'] == 'Debian' && facts[:os]['distro']['codename'] == 'wheezy' 69 | it { 70 | expect(subject).to contain_class('apt::backports') 71 | } 72 | end 73 | 74 | it { 75 | params['prerequired_packages'].each do |package| 76 | expect(subject).to contain_exec('apt_update').that_comes_before("package[#{package}]") 77 | end 78 | 79 | expect(subject).to contain_apt__source('docker').that_comes_before('package[docker]') 80 | } 81 | end 82 | end 83 | when 'RedHat' 84 | if params['manage_package'] 85 | baseurl = case location 86 | when :undef 87 | nil 88 | else 89 | location 90 | end 91 | gpgkey = case key_source 92 | when :undef 93 | nil 94 | else 95 | key_source 96 | end 97 | gpgkey_check = key_check_source 98 | 99 | if params['use_upstream_package_source'] 100 | it { 101 | expect(subject).to contain_yumrepo('docker').with( 102 | 'descr' => 'Docker', 103 | 'baseurl' => baseurl, 104 | 'gpgkey' => gpgkey, 105 | 'gpgcheck' => gpgkey_check, 106 | ).that_comes_before('package[docker]') 107 | } 108 | end 109 | end 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /spec/shared_examples/secrets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'secrets' do |title, params, _facts, defaults| 4 | ensure_value = params['ensure'] 5 | label = params['label'] 6 | secret_name = params['secret_name'] 7 | secret_path = params['secret_path'] 8 | 9 | docker_command = "#{defaults['docker_command']} secret" 10 | 11 | if ensure_value == 'present' 12 | docker_secrets_flags = get_docker_secrets_flags( 13 | 'ensure' => ensure_value, 14 | 'label' => label, 15 | 'secret_name' => secret_name, 16 | 'secret_path' => secret_path, 17 | ) 18 | 19 | exec_secret = "#{docker_command} #{docker_secrets_flags}" 20 | unless_secret = "#{docker_command} inspect #{secret_name}" 21 | 22 | it { 23 | expect(subject).to contain_exec("#{title} docker secret create").with( 24 | 'command' => exec_secret, 25 | 'unless' => unless_secret, 26 | 'path' => ['/bin', '/usr/bin'], 27 | ) 28 | } 29 | end 30 | 31 | if ensure_value == 'absent' 32 | it { 33 | expect(subject).to contain_exec("#{title} docker secret rm").with( 34 | 'command' => "#{docker_command} rm #{secret_name}", 35 | 'onlyif' => "#{docker_command} inspect #{secret_name}", 36 | 'path' => ['/bin', '/usr/bin'], 37 | ) 38 | } 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/shared_examples/stack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'stack' do |_title, params, facts, defaults| 4 | ensure_value = params['ensure'] 5 | stack_name = params['stack_name'] 6 | bundle_file = params['bundle_file'] 7 | compose_files = params['compose_files'] 8 | prune = params['prune'] 9 | with_registry_auth = params['with_registry_auth'] 10 | resolve_image = params['resolve_image'] 11 | 12 | # deprecation('docker::stack','The docker stack define type will be deprecated in a future release. Please migrate to the docker_stack type/provider.') 13 | 14 | docker_command = "#{defaults['docker_command']} stack" 15 | 16 | if facts[:os]['family'] == 'windows' 17 | exec_path = ['C:/Program Files/Docker/'] 18 | check_stack = '$info = docker stack ls | select-string -pattern web 19 | if ($info -eq $null) { Exit 1 } else { Exit 0 }' 20 | provider = 'powershell' 21 | else 22 | exec_path = ['/bin', '/usr/bin'] 23 | check_stack = "#{docker_command} ls | grep '#{stack_name}'" 24 | provider = nil 25 | end 26 | 27 | if ensure_value == 'present' 28 | docker_stack_flags = get_docker_stack_flags( 29 | 'stack_name' => stack_name, 30 | 'bundle_file' => bundle_file, 31 | 'compose_files' => compose_files, 32 | 'prune' => prune, 33 | 'with_registry_auth' => with_registry_auth, 34 | 'resolve_image' => resolve_image, 35 | ) 36 | 37 | exec_stack = "#{docker_command} deploy #{docker_stack_flags} #{stack_name}" 38 | 39 | it { 40 | expect(subject).to contain_exec("docker stack create #{stack_name}").with( 41 | 'command' => exec_stack, 42 | 'unless' => check_stack, 43 | 'path' => exec_path, 44 | 'provider' => provider, 45 | ) 46 | } 47 | end 48 | 49 | if ensure_value == 'absent' 50 | it { 51 | expect(subject).to contain_exec("docker stack destroy #{stack_name}").with( 52 | 'command' => "#{docker_command} rm #{stack_name}", 53 | 'onlyif' => check_stack, 54 | 'path' => exec_path, 55 | 'provider' => provider, 56 | ) 57 | } 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /spec/shared_examples/system_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'system_user' do |user, group| 4 | docker_group = group 5 | 6 | it { 7 | expect(subject).to contain_user(user).with( 8 | 'ensure' => 'present', 9 | ).that_comes_before("Exec[docker-system-user-#{user}]") 10 | } 11 | 12 | it { 13 | expect(subject).to contain_exec("docker-system-user-#{user}").with( 14 | 'command' => "/usr/sbin/usermod -aG #{docker_group} #{user}", 15 | 'unless' => "/bin/cat /etc/group | grep '^#{docker_group}:' | grep -qw #{user}", 16 | ) 17 | } 18 | end 19 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppetlabs_spec_helper/module_spec_helper' 4 | require 'rspec-puppet-facts' 5 | require 'shared_examples' 6 | require 'rspec-puppet' 7 | 8 | require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) 9 | 10 | include RspecPuppetFacts # rubocop:disable Style/MixinUsage 11 | 12 | default_facts = { 13 | puppetversion: Puppet.version, 14 | facterversion: Facter.version 15 | } 16 | 17 | default_fact_files = [ 18 | File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), 19 | File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), 20 | ] 21 | 22 | default_fact_files.each do |f| 23 | next unless File.exist?(f) && File.readable?(f) && File.size?(f) 24 | 25 | begin 26 | default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) 27 | rescue StandardError => e 28 | RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" 29 | end 30 | end 31 | 32 | RSpec.configure do |c| 33 | c.mock_with :rspec 34 | c.default_facts = default_facts 35 | c.before :each do 36 | # set to strictest setting for testing 37 | # by default Puppet runs at warning level 38 | Puppet.settings[:strict] = :warning 39 | end 40 | c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] 41 | end 42 | 43 | # Ensures that a module is defined 44 | # @param module_name Name of the module 45 | def ensure_module_defined(module_name) 46 | module_name.split('::').reduce(Object) do |last_module, next_module| 47 | last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) 48 | last_module.const_get(next_module, false) 49 | end 50 | end 51 | 52 | RSpec::Matchers.define :require_string_for do |property| 53 | match do |type_class| 54 | config = { name: 'name' } 55 | config[property] = 2 56 | expect { 57 | type_class.new(config) 58 | }.to raise_error(Puppet::Error, %r{#{property} should be a String}) 59 | end 60 | failure_message do |type_class| 61 | "#{type_class} should require #{property} to be a String" 62 | end 63 | end 64 | 65 | RSpec::Matchers.define :require_hash_for do |property| 66 | match do |type_class| 67 | config = { name: 'name' } 68 | config[property] = 2 69 | expect { 70 | type_class.new(config) 71 | }.to raise_error(Puppet::Error, %r{#{property} should be a Hash}) 72 | end 73 | failure_message do |type_class| 74 | "#{type_class} should require #{property} to be a Hash" 75 | end 76 | end 77 | 78 | RSpec::Matchers.define :require_array_for do |property| 79 | match do |type_class| 80 | config = { name: 'name' } 81 | config[property] = 2 82 | expect { 83 | type_class.new(config) 84 | }.to raise_error(Puppet::Error, %r{#{property} should be an Array}) 85 | end 86 | failure_message do |type_class| 87 | "#{type_class} should require #{property} to be an Array" 88 | end 89 | end 90 | 91 | at_exit { RSpec::Puppet::Coverage.report! } 92 | 93 | # 'spec_overrides' from sync.yml will appear below this line 94 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet_litmus' 4 | require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_acceptance_local.rb')) 5 | 6 | PuppetLitmus.configure! 7 | -------------------------------------------------------------------------------- /spec/unit/lib/puppet/parser/functions/docker_run_flags_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'the "docker_run_flags" parser function' do 6 | before :each do 7 | Puppet[:modulepath] = 'spec/fixtures/modules' 8 | end 9 | 10 | let :scope do 11 | node = Puppet::Node.new('localhost') 12 | compiler = Puppet::Parser::Compiler.new(node) 13 | scope = Puppet::Parser::Scope.new(compiler) 14 | allow(scope).to receive(:environment).and_return(nil) 15 | allow(scope).to receive(:[]).with('facts').and_return({ 'os' => { 'family' => os_family } }) 16 | scope 17 | end 18 | 19 | context 'on POSIX system' do 20 | let(:os_family) { 'Linux' } 21 | 22 | it 'escapes special chars' do 23 | expect(scope.function_docker_run_flags([{ 'env' => [%.MYSQL_PASSWORD='"$()[]{}<>.], 'extra_params' => [] }])).to eq(%(-e MYSQL_PASSWORD\\=\\'\\"\\$\\(\\)\\[\\]\\{\\}\\<\\> \\\n)) 24 | end 25 | end 26 | 27 | context 'on windows' do 28 | let(:os_family) { 'windows' } 29 | 30 | it 'escapes special chars' do 31 | expect(scope.function_docker_run_flags([{ 'env' => [%.MYSQL_PASSWORD='"$()[]{}<>.], 'extra_params' => [] }])).to eq(%^-e MYSQL_PASSWORD=`'\\`"`$()[]{}<> \\\n^) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/unit/lib/puppet/provider/docker_network_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:docker_network).provider(:ruby) do 6 | let(:provider) { resource.provider } 7 | let(:instance) { provider.class.instances.first } 8 | let(:resource) do 9 | Puppet::Type.type(:docker_network).new( 10 | ensure: :present, 11 | name: 'test-network', 12 | driver: 'host', 13 | subnet: ['192.168.3.0/24', '10.0.0.0/24'], 14 | ) 15 | end 16 | 17 | before :each do 18 | # need to reach deep into puppet to unhook the confinement call, so the provider gets properly loaded 19 | ['docker', '/usr/local/bin/docker'].each do |docker_path| 20 | allow(Puppet::Confine::Exists).to receive(:which).with(docker_path).and_return('/usr/local/bin/docker') 21 | end 22 | end 23 | 24 | describe 'create' do 25 | it 'creates a docker network' do 26 | provider.class.expects(:docker).with(['network', 'create', "--driver=#{resource[:driver]}", "--subnet=#{resource[:subnet][0]}", "--subnet=#{resource[:subnet][1]}", resource[:name]]) 27 | expect(provider.create).to be_nil 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/unit/lib/puppet/type/docker_compose_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | compose = Puppet::Type.type(:docker_compose) 6 | 7 | describe compose do 8 | let :params do 9 | [ 10 | :name, 11 | :provider, 12 | :scale, 13 | :options, 14 | :up_args, 15 | ] 16 | end 17 | 18 | let :properties do 19 | [ 20 | :ensure, 21 | ] 22 | end 23 | 24 | it 'has expected properties' do 25 | properties.each do |property| 26 | expect(compose.properties.map(&:name)).to be_include(property) 27 | end 28 | end 29 | 30 | it 'has expected parameters' do 31 | params.each do |param| 32 | expect(compose.parameters).to be_include(param) 33 | end 34 | end 35 | 36 | it 'requires options to be an array' do 37 | expect(compose).to require_array_for('options') 38 | end 39 | 40 | it 'requires up_args to be a string' do 41 | expect(compose).to require_string_for('up_args') 42 | end 43 | 44 | it 'requires scale to be a hash' do 45 | expect(compose).to require_hash_for('scale') 46 | end 47 | 48 | it 'requires tmpdir to be a string' do 49 | expect(compose).to require_string_for('tmpdir') 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/unit/lib/puppet/type/docker_network_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | network = Puppet::Type.type(:docker_network) 6 | 7 | describe network do 8 | let :params do 9 | [ 10 | :name, 11 | :provider, 12 | :subnet, 13 | :gateway, 14 | :ip_range, 15 | :aux_address, 16 | :options, 17 | :additional_flags, 18 | ] 19 | end 20 | 21 | let :properties do 22 | [ 23 | :ensure, 24 | :driver, 25 | :ipam_driver, 26 | :id, 27 | ] 28 | end 29 | 30 | it 'has expected properties' do 31 | properties.each do |property| 32 | expect(network.properties.map(&:name)).to be_include(property) 33 | end 34 | end 35 | 36 | it 'has expected parameters' do 37 | params.each do |param| 38 | expect(network.parameters).to be_include(param) 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /spec/unit/lib/puppet/type/docker_stack_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | stack = Puppet::Type.type(:docker_stack) 6 | 7 | describe stack do 8 | let :params do 9 | [ 10 | :name, 11 | :provider, 12 | :up_args, 13 | ] 14 | end 15 | 16 | let :properties do 17 | [ 18 | :ensure, 19 | ] 20 | end 21 | 22 | it 'has expected properties' do 23 | properties.each do |property| 24 | expect(stack.properties.map(&:name)).to be_include(property) 25 | end 26 | end 27 | 28 | it 'has expected parameters' do 29 | params.each do |param| 30 | expect(stack.parameters).to be_include(param) 31 | end 32 | end 33 | 34 | it 'requires up_args to be a string' do 35 | expect(stack).to require_string_for('up_args') 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/unit/lib/puppet/type/docker_volume_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | volume = Puppet::Type.type(:docker_volume) 6 | 7 | describe volume do 8 | let :params do 9 | [ 10 | :name, 11 | :provider, 12 | :options, 13 | ] 14 | end 15 | 16 | let :properties do 17 | [ 18 | :driver, 19 | :mountpoint, 20 | ] 21 | end 22 | 23 | it 'has expected properties' do 24 | properties.each do |property| 25 | expect(volume.properties.map(&:name)).to be_include(property) 26 | end 27 | end 28 | 29 | it 'has expected parameters' do 30 | params.each do |param| 31 | expect(volume.parameters).to be_include(param) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /tasks/node_ls.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "List nodes in the swarm", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "filter": { 6 | "description": "Filter output based on conditions provided", 7 | "type": "Optional[String[1]]" 8 | }, 9 | "quiet": { 10 | "description": "Only display IDs", 11 | "type": "Optional[Boolean]" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tasks/node_ls.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def node_ls(filter, quiet) 9 | cmd_string = 'docker node ls' 10 | cmd_string += " --filter=#{filter}" unless filter.nil? 11 | cmd_string += ' --quiet' unless quiet.nil? 12 | 13 | stdout, stderr, status = Open3.capture3(cmd_string) 14 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 15 | 16 | stdout.strip 17 | end 18 | 19 | params = JSON.parse($stdin.read) 20 | filter = params['filter'] 21 | quiet = params['quiet'] 22 | 23 | begin 24 | result = node_ls(filter, quiet) 25 | puts result 26 | exit 0 27 | rescue Puppet::Error => e 28 | puts(status: 'failure', error: e.message) 29 | exit 1 30 | end 31 | -------------------------------------------------------------------------------- /tasks/node_rm.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Update a node", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "force": { 6 | "description": "Force remove a node from the swarm", 7 | "type": "Optional[Boolean]" 8 | }, 9 | "node": { 10 | "description": "Hostname or ID of the node in the swarm", 11 | "type": "String[1]" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tasks/node_rm.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def node_rm(force, node) 9 | cmd_string = 'docker node rm' 10 | cmd_string += ' --force' unless force.nil? 11 | cmd_string += " #{node}" unless node.nil? 12 | 13 | stdout, stderr, status = Open3.capture3(cmd_string) 14 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 15 | 16 | stdout.strip 17 | end 18 | 19 | params = JSON.parse($stdin.read) 20 | force = params['force'] 21 | node = params['node'] 22 | 23 | begin 24 | result = node_rm(force, node) 25 | puts result 26 | exit 0 27 | rescue Puppet::Error => e 28 | puts(status: 'failure', error: e.message) 29 | exit 1 30 | end 31 | -------------------------------------------------------------------------------- /tasks/node_update.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Update a node", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "availability": { 6 | "description": "Availability of the node", 7 | "type": "Optional[Enum['active', 'pause', 'drain']]" 8 | }, 9 | "role": { 10 | "description": "Role of the node", 11 | "type": "Optional[Enum['manager', 'worker']]" 12 | }, 13 | "label_add": { 14 | "description": "Add or update a node label (key=value)", 15 | "type": "Optional[Array]" 16 | }, 17 | "label_rm": { 18 | "description": "Remove a node label if exists.", 19 | "type": "Optional[Array]" 20 | }, 21 | "node": { 22 | "description": "ID of the node in the swarm", 23 | "type": "String[1]" 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /tasks/node_update.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def node_update(availability, role, label_add, label_rm, node) 9 | cmd_string = 'docker node update' 10 | cmd_string += " --availability #{availability}" unless availability.nil? 11 | cmd_string += " --role #{role}" unless role.nil? 12 | 13 | if label_add.is_a? Array 14 | label_add.each do |param| 15 | cmd_string += " --label-add #{param}" 16 | end 17 | end 18 | 19 | if label_rm.is_a? Array 20 | label_rm.each do |param| 21 | cmd_string += " --label-rm #{param}" 22 | end 23 | end 24 | 25 | cmd_string += " #{node}" unless node.nil? 26 | 27 | stdout, stderr, status = Open3.capture3(cmd_string) 28 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 29 | 30 | stdout.strip 31 | end 32 | 33 | params = JSON.parse($stdin.read) 34 | availability = params['availability'] 35 | role = params['role'] 36 | label_add = params['label_add'] 37 | label_rm = params['label_rm'] 38 | node = params['node'] 39 | 40 | begin 41 | result = node_update(availability, role, label_add, label_rm, node) 42 | puts result 43 | exit 0 44 | rescue Puppet::Error => e 45 | puts(status: 'failure', error: e.message) 46 | exit 1 47 | end 48 | -------------------------------------------------------------------------------- /tasks/service_create.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Create a new Docker service", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "service": { 6 | "description": "The name of the service to create", 7 | "type": "String[1]" 8 | }, 9 | "image": { 10 | "description": "The new image to use for the service", 11 | "type": "String[1]" 12 | }, 13 | "replicas": { 14 | "description": "Number of replicas", 15 | "type": "Integer" 16 | }, 17 | "expose": { 18 | "description": "Publish service ports externally to the swarm", 19 | "type": "Variant[String,Array,Undef]" 20 | }, 21 | "env": { 22 | "description": "Set environment variables", 23 | "type": "Optional[Hash]" 24 | }, 25 | "command": { 26 | "description": "Command to run on the container", 27 | "type": "Variant[String,Array,Undef]" 28 | }, 29 | "extra_params": { 30 | "description": "Allows you to pass any other flag that the Docker service create supports.", 31 | "type": "Optional[Array]" 32 | }, 33 | "detach": { 34 | "description": "Exit immediately instead of waiting for the service to converge", 35 | "type": "Optional[Boolean]" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tasks/service_create.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def service_create(image, replicas, expose, env, command, extra_params, service, detach) 9 | cmd_string = 'docker service create' 10 | if extra_params.is_a? Array 11 | extra_params.each do |param| 12 | cmd_string += " #{param}" 13 | end 14 | end 15 | cmd_string += " --name #{service}" unless service.nil? 16 | cmd_string += " --replicas #{replicas}" unless replicas.nil? 17 | cmd_string += " --publish #{expose}" unless expose.nil? 18 | if env.is_a? Hash 19 | env.each do |key, value| 20 | cmd_string += " --env #{key}='#{value}'" 21 | end 22 | end 23 | 24 | if command.is_a? Array 25 | cmd_string += command.join(' ') 26 | elsif command && command.to_s != 'undef' 27 | cmd_string += command.to_s 28 | end 29 | 30 | cmd_string += ' -d' unless detach.nil? 31 | cmd_string += " #{image}" unless image.nil? 32 | 33 | stdout, stderr, status = Open3.capture3(cmd_string) 34 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 35 | 36 | stdout.strip 37 | end 38 | 39 | params = JSON.parse($stdin.read) 40 | image = params['image'] 41 | replicas = params['replicas'] 42 | expose = params['expose'] 43 | env = params['env'] 44 | command = params['command'] 45 | extra_params = params['extra_params'] 46 | service = params['service'] 47 | detach = params['detach'] 48 | 49 | begin 50 | result = service_create(image, replicas, expose, env, command, extra_params, service, detach) 51 | puts result 52 | exit 0 53 | rescue Puppet::Error => e 54 | puts(status: 'failure', error: e.message) 55 | exit 1 56 | end 57 | -------------------------------------------------------------------------------- /tasks/service_rm.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Remove one replicated service", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "service": { 6 | "description": "Name or ID of the service", 7 | "type": "String[1]" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tasks/service_rm.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def service_rm(service) 9 | cmd_string = 'docker service rm' 10 | cmd_string += " #{service}" unless service.nil? 11 | 12 | stdout, stderr, status = Open3.capture3(cmd_string) 13 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 14 | 15 | stdout.strip 16 | end 17 | 18 | params = JSON.parse($stdin.read) 19 | service = params['service'] 20 | 21 | begin 22 | result = service_rm(service) 23 | puts result 24 | exit 0 25 | rescue Puppet::Error => e 26 | puts(status: 'failure', error: e.message) 27 | exit 1 28 | end 29 | -------------------------------------------------------------------------------- /tasks/service_scale.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Scale one replicated service", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "service": { 6 | "description": "Name or ID of the service", 7 | "type": "String[1]" 8 | }, 9 | "scale": { 10 | "description": "Number of replicas", 11 | "type": "Integer" 12 | }, 13 | "detach": { 14 | "description": "Exit immediately instead of waiting for the service to converge", 15 | "type": "Optional[Boolean]" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tasks/service_scale.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def service_scale(service, scale, detach) 9 | cmd_string = 'docker service scale' 10 | cmd_string += " #{service}" unless service.nil? 11 | cmd_string += "=#{scale}" unless scale.nil? 12 | cmd_string += ' -d' unless detach.nil? 13 | 14 | stdout, stderr, status = Open3.capture3(cmd_string) 15 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 16 | 17 | stdout.strip 18 | end 19 | 20 | params = JSON.parse($stdin.read) 21 | service = params['service'] 22 | scale = params['scale'] 23 | detach = params['detach'] 24 | 25 | begin 26 | result = service_scale(service, scale, detach) 27 | puts result 28 | exit 0 29 | rescue Puppet::Error => e 30 | puts(status: 'failure', error: e.message) 31 | exit 1 32 | end 33 | -------------------------------------------------------------------------------- /tasks/service_update.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Updates an existing service.", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "service": { 6 | "description": "The service to update", 7 | "type": "String[1]" 8 | }, 9 | "image": { 10 | "description": "The new image to use for the service", 11 | "type": "String[1]" 12 | }, 13 | "constraint_add": { 14 | "description": "Add or update a service constraint (selector==value, selector!=value)", 15 | "type": "Optional[Array]" 16 | }, 17 | "constraint_rm": { 18 | "description": "Remove a service constraint if exists.", 19 | "type": "Optional[Array]" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tasks/service_update.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def service_update(image, service, constraint_add, constraint_rm) 9 | cmd_string = 'docker service update' 10 | cmd_string += " --image #{image}" unless image.nil? 11 | 12 | if constraint_add.is_a? Array 13 | constraint_add.each do |param| 14 | cmd_string += " --constraint-add #{param}" 15 | end 16 | end 17 | 18 | if constraint_rm.is_a? Array 19 | constraint_rm.each do |param| 20 | cmd_string += " --constraint-rm #{param}" 21 | end 22 | end 23 | 24 | cmd_string += " #{service}" unless service.nil? 25 | 26 | stdout, stderr, status = Open3.capture3(cmd_string) 27 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 28 | 29 | stdout.strip 30 | end 31 | 32 | params = JSON.parse($stdin.read) 33 | image = params['image'] 34 | service = params['service'] 35 | constraint_add = params['constraint_add'] 36 | constraint_rm = params['constraint_rm'] 37 | 38 | begin 39 | result = service_update(image, service, constraint_add, constraint_rm) 40 | puts result 41 | exit 0 42 | rescue Puppet::Error => e 43 | puts(status: 'failure', error: e.message) 44 | exit 1 45 | end 46 | -------------------------------------------------------------------------------- /tasks/swarm_init.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Initializes a swarm", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "advertise_addr": { 6 | "description": "Advertised address", 7 | "type": "Optional[String[1]]" 8 | }, 9 | "autolock": { 10 | "description": "Enable manager autolocking", 11 | "type": "Optional[Boolean]" 12 | }, 13 | "cert_expiry": { 14 | "description": "Validity period for node certificates", 15 | "type": "Optional[String[1]]" 16 | }, 17 | "dispatcher_heartbeat": { 18 | "description": "Dispatcher heartbeat period", 19 | "type": "Optional[String[1]]" 20 | }, 21 | "external_ca": { 22 | "description": "Specifications of one or more certificate signing endpoints", 23 | "type": "Optional[String[1]]" 24 | }, 25 | "force_new_cluster": { 26 | "description": "Force create a new cluster from current state", 27 | "type": "Optional[Boolean]" 28 | }, 29 | "listen_addr": { 30 | "description": "Listen address", 31 | "type": "Optional[String[1]]" 32 | }, 33 | "max_snapshots": { 34 | "description": "Number of additional Raft snapshots to retain", 35 | "type": "Optional[Integer[1]]" 36 | }, 37 | "snapshot_interval": { 38 | "description": "Number of log entries between Raft snapshots", 39 | "type": "Optional[Integer[1]]" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /tasks/swarm_init.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def swarm_init(advertise_addr, autolock, cert_expiry, dispatcher_heartbeat, external_ca, force_new_cluster, listen_addr, max_snapshots, snapshot_interval) 9 | cmd_string = 'docker swarm init' 10 | cmd_string += " --advertise-addr=#{advertise_addr}" unless advertise_addr.nil? 11 | cmd_string += ' --autolock' unless autolock.nil? 12 | cmd_string += ' --cert-expiry' unless cert_expiry.nil? 13 | cmd_string += " --dispatcher-heartbeat=#{dispatcher_heartbeat}" unless dispatcher_heartbeat.nil? 14 | cmd_string += " --external-ca=#{external_ca}" unless external_ca.nil? 15 | cmd_string += ' --force-new-cluster' unless force_new_cluster.nil? 16 | cmd_string += " --listen-addr=#{listen_addr}" unless listen_addr.nil? 17 | cmd_string += " --max-snapshots=#{max_snapshots}" unless max_snapshots.nil? 18 | cmd_string += " --snapshot-interval=#{snapshot_interval}" unless snapshot_interval.nil? 19 | 20 | stdout, stderr, status = Open3.capture3(cmd_string) 21 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 22 | 23 | stdout.strip 24 | end 25 | 26 | params = JSON.parse($stdin.read) 27 | advertise_addr = params['advertise_addr'] 28 | autolock = params['autolock'] 29 | cert_expiry = params['cert_expiry'] 30 | dispatcher_heartbeat = params['dispatcher_heartbeat'] 31 | external_ca = params['external_ca'] 32 | force_new_cluster = params['force_new_cluster'] 33 | listen_addr = params['listen_addr'] 34 | max_snapshots = params['max_snapshots'] 35 | snapshot_interval = params['snapshot_interval'] 36 | 37 | begin 38 | result = swarm_init(advertise_addr, autolock, cert_expiry, dispatcher_heartbeat, external_ca, force_new_cluster, listen_addr, max_snapshots, snapshot_interval) 39 | puts result 40 | exit 0 41 | rescue Puppet::Error => e 42 | puts(status: 'failure', error: e.message) 43 | exit 1 44 | end 45 | -------------------------------------------------------------------------------- /tasks/swarm_join.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Join a swarm", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "advertise_addr": { 6 | "description": "Advertised address", 7 | "type": "Optional[String[1]]" 8 | }, 9 | "listen_addr": { 10 | "description": "Listen address", 11 | "type": "Optional[String[1]]" 12 | }, 13 | "token": { 14 | "description": "Join token for the swarm", 15 | "type": "String[1]" 16 | }, 17 | "manager_ip": { 18 | "description": "IP Address of the swarm manager", 19 | "type": "String[1]" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /tasks/swarm_join.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def swarm_join(advertise_addr, listen_addr, token, manager_ip) 9 | cmd_string = 'docker swarm join' 10 | cmd_string += " --advertise-addr=#{advertise_addr}" unless advertise_addr.nil? 11 | cmd_string += " --listen-addr=#{listen_addr}" unless listen_addr.nil? 12 | cmd_string += " --token=#{token}" unless token.nil? 13 | cmd_string += " #{manager_ip}" unless manager_ip.nil? 14 | 15 | stdout, stderr, status = Open3.capture3(cmd_string) 16 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 17 | 18 | stdout.strip 19 | end 20 | 21 | params = JSON.parse($stdin.read) 22 | advertise_addr = params['advertise_addr'] 23 | listen_addr = params['listen_addr'] 24 | token = params['token'] 25 | manager_ip = params['manager_ip'] 26 | 27 | begin 28 | result = swarm_join(advertise_addr, listen_addr, token, manager_ip) 29 | puts result 30 | exit 0 31 | rescue Puppet::Error => e 32 | puts(status: 'failure', error: e.message) 33 | exit 1 34 | end 35 | -------------------------------------------------------------------------------- /tasks/swarm_leave.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Leave a swarm", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "force": { 6 | "description": "Force this node to leave the swarm, ignoring warnings", 7 | "type": "Optional[Boolean]" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /tasks/swarm_leave.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def swarm_leave(force) 9 | cmd_string = 'docker swarm leave ' 10 | cmd_string += ' -f' if force == 'true' 11 | stdout, stderr, status = Open3.capture3(cmd_string) 12 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 13 | 14 | stdout.strip 15 | end 16 | 17 | params = JSON.parse($stdin.read) 18 | force = params['force'] 19 | begin 20 | result = swarm_leave(force) 21 | puts result 22 | exit 0 23 | rescue Puppet::Error => e 24 | puts(status: 'failure', error: e.message) 25 | exit 1 26 | end 27 | -------------------------------------------------------------------------------- /tasks/swarm_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Gets the swarm token from the server", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "node_role": { 6 | "description": "The role of the node joining the swarm", 7 | "type": "String[1]" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /tasks/swarm_token.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | def swarm_token(node_role) 9 | cmd_string = 'docker swarm join-token -q' 10 | cmd_string += " #{node_role}" unless node_role.nil? 11 | 12 | stdout, stderr, status = Open3.capture3(cmd_string) 13 | raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 14 | 15 | stdout.strip 16 | end 17 | 18 | params = JSON.parse($stdin.read) 19 | node_role = params['node_role'] 20 | 21 | begin 22 | result = swarm_token(node_role) 23 | puts result 24 | exit 0 25 | rescue Puppet::Error => e 26 | puts(status: 'failure', error: e.message) 27 | exit 1 28 | end 29 | -------------------------------------------------------------------------------- /tasks/swarm_update.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Updates an existing service.", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "service": { 6 | "description": "The service to update", 7 | "type": "String[1]" 8 | }, 9 | "image": { 10 | "description": "The new image to use for the service", 11 | "type": "String[1]" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tasks/swarm_update.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | require 'open3' 6 | require 'puppet' 7 | 8 | params = JSON.parse($stdin.read) 9 | image = params['image'] 10 | service = params['service'] 11 | 12 | begin 13 | puts 'Deprecated: use docker::service_update instead' 14 | result = service_update(image, service) 15 | puts result 16 | exit 0 17 | rescue Puppet::Error => e 18 | puts(status: 'failure', error: e.message) 19 | exit 1 20 | end 21 | -------------------------------------------------------------------------------- /templates/docker-run-start.epp: -------------------------------------------------------------------------------- 1 | <% if $before_start { -%> 2 | <%= $before_start %> 3 | <% } -%> 4 | <% if $remove_container_on_start { -%> 5 | /usr/bin/<%= $docker_command %> rm <% if $remove_volume_on_start { %>-v<% } %> <%= $sanitised_title %> >/dev/null 2>&1 6 | <% } -%> 7 | 8 | <% if $pull_on_start { -%> 9 | /usr/bin/<%= $docker_command %> pull <%= $image %> 10 | <% } -%> 11 | 12 | <% if $verify_digest { -%> 13 | digest_local=$(docker image inspect <%= $image %> --format='{{index .RepoDigests 0}}') 14 | digest_verify="<%= $verify_digest %>" 15 | if [ "${digest_local##*:}" != "${digest_verify##*:}" ]; then 16 | echo "Digest verify failed! Expected checksum 'sha256:$digest_verify' does not match with local checksum 'sha256:$digest_local'!" 17 | exit 2 18 | fi 19 | <% } -%> 20 | 21 | /usr/bin/<%= $docker_command %> create \ 22 | <%= $docker_run_flags %> \ 23 | --name <%= $sanitised_title %> \ 24 | <%= $image %> <% if $command { %> \ 25 | <%= $command %><% } %> 26 | 27 | <% if $after_create { %><%= $after_create %><% } %> 28 | <% if String(type($net, 'generalized')).index('Array') == 0 { %> 29 | <% $net.each |$n| { %> 30 | /usr/bin/<%= $docker_command %> network connect <%= $n %> <%= $sanitised_title %> 31 | <% } %> 32 | <% } %> 33 | 34 | /usr/bin/<%= $docker_command %> start <% if ! $valid_detach { %>-a<% } %> <%= $sanitised_title %> 35 | <% if $after_start { -%> 36 | <%= $after_start %> 37 | <% } -%> 38 | -------------------------------------------------------------------------------- /templates/docker-run-stop.epp: -------------------------------------------------------------------------------- 1 | <% if $before_stop { -%> 2 | <%= $before_stop %> 3 | <% } -%> 4 | /usr/bin/<%= $docker_command %> stop --time=<%= $stop_wait_time %> <%= $sanitised_title %> 5 | <% if $remove_container_on_stop { -%> 6 | /usr/bin/<%= $docker_command %> rm <% if $remove_volume_on_stop { %>-v<% } %> <%= $sanitised_title %> 7 | <% } -%> 8 | <% if $after_stop { -%> 9 | <%= $after_stop %> 10 | <% } -%> 11 | -------------------------------------------------------------------------------- /templates/etc/conf.d/docker.epp: -------------------------------------------------------------------------------- 1 | # This file is managed by Puppet and local changes 2 | # may be overwritten 3 | 4 | DOCKER="/usr/bin/<%= $docker_start_command %>" 5 | 6 | other_args="<% -%> 7 | <% if $root_dir { %><%= $root_dir_flag %> <%= $root_dir %><% } -%> 8 | <% if $tcp_bind { %><% $tcp_bind_array.each |$param| { %> -H <%= $param %><% } %><% } -%> 9 | <% if $tls_enable { %> --tls<% if $tls_verify { %> --tlsverify<% } %> --tlscacert=<%= $tls_cacert %> --tlscert=<%= $tls_cert %> --tlskey=<%= $tls_key %><% } -%> 10 | <% if $socket_bind { %> -H <%= $socket_bind %><% } -%> 11 | --ip-forward=<%= $ip_forward -%> 12 | --iptables=<%= $iptables -%> 13 | --ip-masq=<%= $ip_masq -%> 14 | <% if $icc { %> --icc=<%= $icc %><% } -%> 15 | <% if $fixed_cidr { %> --fixed-cidr <%= $fixed_cidr %><% } -%> 16 | <% if $default_gateway { %> --default-gateway <%= $default_gateway %><% } -%> 17 | <% if $bridge { %> --bridge <%= $bridge %><% } -%> 18 | <% if $log_level { %> -l <%= $log_level %><% } -%> 19 | <% if $log_driver { %> --log-driver <%= $log_driver %><% } -%> 20 | <% if $log_driver { %><% if $log_opt { %><% $log_opt.each |$param| { %> --log-opt <%= $param %><% } %><% } -%><% } -%> 21 | <% if $selinux_enabled { %> --selinux-enabled=<%= $selinux_enabled %><% } -%> 22 | <% if $socket_group { %> -G <%= $socket_group %><% } -%> 23 | <% if $dns { %><% $dns_array.each |$address| { %> --dns <%= $address %><% } %><% } -%> 24 | <% if $dns_search { %><% $dns_search_array.each |$domain| { %> --dns-search <%= $domain %><% } %><% } -%> 25 | <% if $execdriver { %> -e <%= $execdriver %><% } -%> 26 | <% if $storage_driver { %> --storage-driver=<%= $storage_driver %><% } -%> 27 | <% if $storage_driver == 'devicemapper' { -%> 28 | <%- if $dm_basesize { %> --storage-opt dm.basesize=<%= $dm_basesize %><% } -%> 29 | <%- if $dm_fs { %> --storage-opt dm.fs=<%= $dm_fs %><% } -%> 30 | <%- if $dm_mkfsarg { %> --storage-opt "dm.mkfsarg=<%= $dm_mkfsarg %>"<% } -%> 31 | <%- if $dm_mountopt { %> --storage-opt dm.mountopt=<%= $dm_mountopt %><% } -%> 32 | <%- if $dm_blocksize { %> --storage-opt dm.blocksize=<%= $dm_blocksize %><% } -%> 33 | <%- if $dm_loopdatasize { %> --storage-opt dm.loopdatasize=<%= $dm_loopdatasize %><% } -%> 34 | <%- if $dm_loopmetadatasize { %> --storage-opt dm.loopmetadatasize=<%= $dm_loopmetadatasize %><% } -%> 35 | <%- if $dm_thinpooldev { %> --storage-opt dm.thinpooldev=<%= $dm_thinpooldev -%> 36 | <%- }else { -%> 37 | <%- if $dm_datadev { %> --storage-opt dm.datadev=<%= $dm_datadev %><% } -%> 38 | <%- if $dm_metadatadev { %> --storage-opt dm.metadatadev=<%= $dm_metadatadev %><% } -%> 39 | <%- } -%> 40 | <%- if $dm_use_deferred_removal { %> --storage-opt dm.use_deferred_removal=<%= $dm_use_deferred_removal %><% } -%> 41 | <%- if $dm_use_deferred_deletion { %> --storage-opt dm.use_deferred_deletion=<%= $dm_use_deferred_deletion %><% } -%> 42 | <%- if $dm_blkdiscard { %> --storage-opt dm.blkdiscard=<%= $dm_blkdiscard %><% } -%> 43 | <%- if $dm_override_udev_sync_check { %> --storage-opt dm.override_udev_sync_check=<%= $dm_override_udev_sync_check %><% } -%> 44 | <% } elsif $storage_driver == 'overlay2' { -%> 45 | <%- if $overlay2_override_kernel_check { %> --storage-opt overlay2.override_kernel_check=<%= $overlay2_override_kernel_check %><% } -%> 46 | <% } -%> 47 | <% $labels.each |$label| { %> --label <%= $label %><% } -%> 48 | <% if $extra_parameters { %><% $extra_parameters_array.each |$param| { %> <%= $param %><% } %><% } -%> 49 | " 50 | <% if $proxy { %>export http_proxy='<%= $proxy %>' 51 | export https_proxy='<%= $proxy %>'<% } %> 52 | <% if $no_proxy { %>export no_proxy='<%= $no_proxy %>'<% } %> 53 | # This is also a handy place to tweak where Docker's temporary files go. 54 | export TMPDIR="<%= $tmp_dir %>" 55 | <% if $shell_values { %><% $shell_values_array.each |$param| { %> 56 | <%= $param %><% } %><% } -%> 57 | -------------------------------------------------------------------------------- /templates/etc/conf.d/docker.gentoo.epp: -------------------------------------------------------------------------------- 1 | # This file is managed by Puppet and local changes 2 | # may be overwritten 3 | 4 | DOCKER_BINARY="/usr/bin/<%= $docker_command %>" 5 | 6 | DOCKER_OPTS="<% -%> 7 | <% if $root_dir { %> -g <%= $root_dir %><% } %> 8 | <% if $tcp_bind { %><% $tcp_bind_array.each |$param| { %> -H <%= $param %><% } %><% } %> 9 | <% if $tls_enable { %> --tls<% if $tls_verify { %> --tlsverify<% } %> --tlscacert=<%= $tls_cacert %> --tlscert=<%= $tls_cert %> --tlskey=<%= $tls_key %><% } %> 10 | <% if $socket_bind { %> -H <%= $socket_bind %><% } %> 11 | --ip-forward=<%= $ip_forward -%> 12 | --iptables=<%= $iptables -%> 13 | --ip-masq=<%= $ip_masq -%> 14 | <% if $icc { %> --icc=<%= $icc %><% } %> 15 | <% if $fixed_cidr { %> --fixed-cidr <%= $fixed_cidr %><% } %> 16 | <% if $default_gateway { %> --default-gateway <%= $default_gateway %><% } %> 17 | <% if $bridge { %> --bridge <%= $bridge %><% } %> 18 | <% if $log_level { %> -l <%= $log_level %><% } %> 19 | <% if $log_driver { %> --log-driver <%= $log_driver %><% } %> 20 | <% if $log_driver { %><% if $log_opt { %><% $log_opt.each |$param| { %> --log-opt <%= $param %><% } %><% } %><% } %> 21 | <% if $selinux_enabled { %> --selinux-enabled=<%= $selinux_enabled %><% } %> 22 | <% if $socket_group { %> -G <%= $socket_group %><% } %> 23 | <% if $dns { %><% $dns_array.each |$address| { %> --dns <%= $address %><% } %><% } %> 24 | <% if $dns_search { %><% $dns_search_array.each |$domain| { %> --dns-search <%= $domain %><% } %><% } %> 25 | <% if $execdriver { %> -e <%= $execdriver %><% } %> 26 | <% if $storage_driver { %> --storage-driver=<%= $storage_driver %><% } %> 27 | <% if $storage_driver == 'devicemapper' { -%> 28 | <%- if $dm_basesize { %> --storage-opt dm.basesize=<%= $dm_basesize %><% } %> 29 | <%- if $dm_fs { %> --storage-opt dm.fs=<%= $dm_fs %><% } %> 30 | <%- if $dm_mkfsarg { %> --storage-opt "dm.mkfsarg=<%= $dm_mkfsarg %>"<% } %> 31 | <%- if $dm_mountopt { %> --storage-opt dm.mountopt=<%= $dm_mountopt %><% } %> 32 | <%- if $dm_blocksize { %> --storage-opt dm.blocksize=<%= $dm_blocksize %><% } %> 33 | <%- if $dm_loopdatasize { %> --storage-opt dm.loopdatasize=<%= $dm_loopdatasize %><% } %> 34 | <%- if $dm_loopmetadatasize { %> --storage-opt dm.loopmetadatasize=<%= $dm_loopmetadatasize %><% } %> 35 | <%- if $dm_thinpooldev { %> --storage-opt dm.thinpooldev=<%= $dm_thinpooldev %><% } 36 | else { %> 37 | <%- if $dm_datadev { %> --storage-opt dm.datadev=<%= $dm_datadev %><% } %> 38 | <%- if $dm_metadatadev { %> --storage-opt dm.metadatadev=<%= $dm_metadatadev %><% } %> 39 | <% } %> 40 | <%- if $dm_use_deferred_removal { %> --storage-opt dm.use_deferred_removal=<%= $dm_use_deferred_removal %><% } %> 41 | <%- if $dm_use_deferred_deletion { %> --storage-opt dm.use_deferred_deletion=<%= $dm_use_deferred_deletion %><% } %> 42 | <%- if $dm_blkdiscard { %> --storage-opt dm.blkdiscard=<%= $dm_blkdiscard %><% } %> 43 | <%- if $dm_override_udev_sync_check { %> --storage-opt dm.override_udev_sync_check=<%= $dm_override_udev_sync_check %><% } %> 44 | <% } elsif $storage_driver == 'overlay2' { -%> 45 | <%- if $overlay2_override_kernel_check { %> --storage-opt overlay2.override_kernel_check=<%= $overlay2_override_kernel_check %><% } %> 46 | <% } -%> 47 | <% $labels.each |$label| { %> --label <%= $label %><% } %> 48 | <% if $extra_parameters { %><% $extra_parameters_array.each |$param| { %> <%= $param %><% } %><% } %> 49 | " 50 | <% if $proxy { %>export http_proxy='<%= $proxy %>' 51 | export https_proxy='<%= $proxy %>'<% } -%> 52 | <% if $no_proxy { %>export no_proxy='<%= $no_proxy %>'<% } -%> 53 | # This is also a handy place to tweak where Docker's temporary files go. 54 | export TMPDIR="<%= $tmp_dir %>" 55 | <% if $shell_values { %><% $shell_values_array.each |$param| { %> 56 | <%= $param %><% } %><% } -%> 57 | -------------------------------------------------------------------------------- /templates/etc/init.d/docker-run.epp: -------------------------------------------------------------------------------- 1 | <%- 2 | $required_start = ["$network"] + 3 | $sanitised_after_array.map |$s| { "${service_prefix}${s}"} + 4 | $sanitised_depends_array.map |$s| { "${service_prefix}${s}"} + 5 | $depend_services_array 6 | 7 | $required_stop = ["$network"] + 8 | $sanitised_depends_array.map |$d| { "${service_prefix}${d}"} + 9 | $depend_services_array 10 | -%> 11 | #!/bin/sh 12 | # 13 | # This file is managed by Puppet and local changes 14 | # may be overwritten 15 | # 16 | # /etc/rc.d/init.d/ 17 | # 18 | # Daemon for <%= $title %> 19 | # 20 | # chkconfig: 2345 97 15 21 | # description: Docker container for <%= $title %> 22 | 23 | ### BEGIN INIT INFO 24 | # Provides: <%= $service_prefix %><%= $sanitised_title %> 25 | # Required-Start: <%= $required_start.unique.join(" ") %> 26 | # Required-Stop: <%= $required_stop.unique.join(" ") %> 27 | # Should-Start: 28 | # Should-Stop: 29 | # Default-Start: 2 3 4 5 30 | # Default-Stop: 0 1 6 31 | # Short-Description: start and stop docker container for <%= $title %> 32 | # Description: Docker container for <%= $title %> 33 | ### END INIT INFO 34 | 35 | if [ -e /etc/init.d/functions ]; then 36 | . /etc/init.d/functions 37 | elif [ -e /lib/lsb/init-functions ]; then 38 | . /lib/lsb/init-functions 39 | failure() { 40 | log_failure_msg "$@" 41 | return 1 42 | } 43 | success() { 44 | log_success_msg "$@" 45 | return 0 46 | } 47 | else 48 | failure() { 49 | echo "fail: $@" >&2 50 | exit 1 51 | } 52 | success() { 53 | echo "success: $@" >&2 54 | exit 0 55 | } 56 | fi 57 | 58 | export HOME=/root/ 59 | docker="/usr/bin/<%= $docker_command %>" 60 | prog="<%= $service_prefix %><%= $sanitised_title %>" 61 | if [ -d /var/lock/subsys ]; then 62 | lockfile="/var/lock/subsys/$prog" 63 | else 64 | unset lockfile 65 | fi 66 | 67 | start() { 68 | [ -x $docker ] || exit 5 69 | 70 | if [ "true" = "$($docker inspect --format='{{.State.Running}}' <%= $sanitised_title %> 2>/dev/null)" ]; then 71 | failure 72 | printf "Container <%= $sanitised_title %> is still running.\n" 73 | exit 7 74 | fi 75 | 76 | printf "Starting $prog:\t" 77 | <%= $docker_run_inline_start %> 78 | 79 | retval=$? 80 | echo 81 | if [ $retval -eq 0 ]; then 82 | success 83 | else 84 | failure 85 | fi 86 | } 87 | 88 | stop() { 89 | echo -n "Stopping $prog: " 90 | <%= $docker_run_inline_stop %> 91 | 92 | return $? 93 | } 94 | 95 | clean() { 96 | if ! [ -f $cidfile ]; then 97 | failure 98 | echo 99 | printf "$cidfile does not exist.\n" 100 | else 101 | cid="$(cat $cidfile)" 102 | rm $cidfile 103 | $docker rm -v -f $cid 104 | retval=$? 105 | return $retval 106 | fi 107 | } 108 | 109 | case "$1" in 110 | start) 111 | start 112 | ;; 113 | stop) 114 | stop 115 | ;; 116 | status) 117 | if [ "true" = "$($docker inspect --format='{{.State.Running}}' <%= $sanitised_title %> 2>/dev/null)" ]; then 118 | echo $prog is running 119 | exit 0 120 | else 121 | echo $prog not running 122 | exit 1 123 | fi 124 | ;; 125 | restart|reload) 126 | stop 127 | start 128 | ;; 129 | clean) 130 | clean 131 | ;; 132 | cleanRestart) 133 | stop 134 | clean 135 | start 136 | ;; 137 | condrestart) 138 | [ -f /var/lock/subsys/$prog ] && restart || : 139 | ;; 140 | *) 141 | echo "Usage: $0 [start|stop|status|reload|restart|probe|clean|cleanRestart]" 142 | exit 1 143 | ;; 144 | esac 145 | exit $? 146 | -------------------------------------------------------------------------------- /templates/etc/sysconfig/docker-storage-setup.epp: -------------------------------------------------------------------------------- 1 | # This file is managed by Puppet and local changes 2 | # may be overwritten 3 | 4 | # Edit this file to override any configuration options specified in 5 | # /usr/lib/docker-storage-setup/docker-storage-setup. 6 | # 7 | # For more details refer to "man docker-storage-setup" 8 | 9 | <% if $storage_driver { %>STORAGE_DRIVER=<%= $storage_driver %><% } %> 10 | <% if $storage_devs { %>DEVS="<%= $storage_devs %>"<% } %> 11 | <% if $storage_vg { %>VG=<%= $storage_vg %><% } %> 12 | <% if $storage_root_size { %>ROOT_SIZE=<%= $storage_root_size %><% } %> 13 | <% if $storage_data_size { %>DATA_SIZE=<%= $storage_data_size %><% } %> 14 | <% if $storage_min_data_size { %>MIN_DATA_SIZE=<%= $storage_min_data_size %><% } %> 15 | <% if $storage_chunk_size { %>CHUNK_SIZE=<%= $storage_chunk_size %><% } %> 16 | <% if $storage_growpart { %>GROWPART=<%= $storage_growpart %><% } %> 17 | <% if $storage_auto_extend_pool { %>AUTO_EXTEND_POOL=<%= $storage_auto_extend_pool %><% } %> 18 | <% if $storage_pool_autoextend_threshold { %>POOL_AUTOEXTEND_THRESHOLD=<%= $storage_pool_autoextend_threshold %><% } %> 19 | <% if $storage_pool_autoextend_percent { %>POOL_AUTOEXTEND_PERCENT=<%= $storage_pool_autoextend_percent %><% } %> 20 | -------------------------------------------------------------------------------- /templates/etc/sysconfig/docker-storage.epp: -------------------------------------------------------------------------------- 1 | # This file is managed by Puppet and local changes 2 | # may be overwritten 3 | 4 | # This file may be automatically generated by an installation program. 5 | 6 | # By default, Docker uses a loopback-mounted sparse file in 7 | # /var/lib/docker. The loopback makes it slower, and there are some 8 | # restrictive defaults, such as 100GB max storage. 9 | 10 | # If your installation did not set a custom storage for Docker, you 11 | # may do it below. 12 | 13 | # Example: Use a custom pair of raw logical volumes (one for metadata, 14 | # one for data). 15 | # DOCKER_STORAGE_OPTIONS = --storage-opt dm.metadatadev=/dev/mylogvol/my-docker-metadata --storage-opt dm.datadev=/dev/mylogvol/my-docker-data 16 | 17 | DOCKER_STORAGE_OPTIONS="<% -%> 18 | <% if $storage_driver { %> --storage-driver=<%= $storage_driver %><% } -%> 19 | <% if $storage_driver == 'devicemapper' { -%> 20 | <%- if $dm_basesize { %> --storage-opt dm.basesize=<%= $dm_basesize %><% } -%> 21 | <%- if $dm_fs { %> --storage-opt dm.fs=<%= $dm_fs %><% } -%> 22 | <%- if $dm_mkfsarg { %> --storage-opt "dm.mkfsarg=<%= $dm_mkfsarg %>"<% } -%> 23 | <%- if $dm_mountopt { %> --storage-opt dm.mountopt=<%= $dm_mountopt %><% } -%> 24 | <%- if $dm_blocksize { %> --storage-opt dm.blocksize=<%= $dm_blocksize %><% } -%> 25 | <%- if $dm_loopdatasize { %> --storage-opt dm.loopdatasize=<%= $dm_loopdatasize %><% } -%> 26 | <%- if $dm_loopmetadatasize { %> --storage-opt dm.loopmetadatasize=<%= $dm_loopmetadatasize %><% } -%> 27 | <%- if $dm_thinpooldev { %> --storage-opt dm.thinpooldev=<%= $dm_thinpooldev -%> 28 | <%- }else { -%> 29 | <%- if $dm_datadev { %> --storage-opt dm.datadev=<%= $dm_datadev %><% } -%> 30 | <%- if $dm_metadatadev { %> --storage-opt dm.metadatadev=<%= $dm_metadatadev %><% } -%> 31 | <%- } -%> 32 | <%- if $dm_use_deferred_removal { %> --storage-opt dm.use_deferred_removal=<%= $dm_use_deferred_removal %><% } -%> 33 | <%- if $dm_use_deferred_deletion { %> --storage-opt dm.use_deferred_deletion=<%= $dm_use_deferred_deletion %><% } -%> 34 | <%- if $dm_blkdiscard { %> --storage-opt dm.blkdiscard=<%= $dm_blkdiscard %><% } -%> 35 | <%- if $dm_override_udev_sync_check { %> --storage-opt dm.override_udev_sync_check=<%= $dm_override_udev_sync_check %><% } -%> 36 | <% } elsif $storage_driver == 'overlay2' { -%> 37 | <%- if $overlay2_override_kernel_check { %> --storage-opt overlay2.override_kernel_check=<%= $overlay2_override_kernel_check %><% } -%> 38 | <% } -%> 39 | " 40 | -------------------------------------------------------------------------------- /templates/etc/sysconfig/docker.epp: -------------------------------------------------------------------------------- 1 | # This file is managed by Puppet and local changes 2 | # may be overwritten 3 | 4 | DOCKER="/usr/bin/<%= $docker_command %>" 5 | 6 | other_args="<% -%> 7 | <% if $root_dir { %><%= $root_dir_flag %> <%= $root_dir %><% } -%> 8 | <% if $tcp_bind { %><% $tcp_bind_array.each |$param| { %> -H <%= $param %><% } %><% } -%> 9 | <% if $tls_enable { %> --tls<% if $tls_verify { %> --tlsverify<% } %> --tlscacert=<%= $tls_cacert %> --tlscert=<%= $tls_cert %> --tlskey=<%= $tls_key %><% } -%> 10 | <% if $socket_bind { %> -H <%= $socket_bind %><% } -%> 11 | --ip-forward=<%= $ip_forward -%> 12 | --iptables=<%= $iptables -%> 13 | --ip-masq=<%= $ip_masq -%> 14 | <% if $icc { %> --icc=<%= $icc %><% } -%> 15 | <% if $fixed_cidr { %> --fixed-cidr <%= $fixed_cidr %><% } -%> 16 | <% if $bridge { %> --bridge <%= $bridge %><% } -%> 17 | <% if $default_gateway { %> --default-gateway <%= $default_gateway %><% } -%> 18 | <% if $ipv6 { %> --ipv6<% } -%> 19 | <% if $ipv6_cidr { %> --fixed-cidr-v6 <%= $ipv6_cidr %><% } -%> 20 | <% if $default_gateway_ipv6 { %> --default-gateway-v6 <%= $default_gateway_ipv6 %><% } -%> 21 | <% if $log_level { %> -l <%= $log_level %><% } -%> 22 | <% if $log_driver { %> --log-driver <%= $log_driver %><% } -%> 23 | <% if $log_driver { %><% if $log_opt { %><% $log_opt.each |$param| { %> --log-opt <%= $param %><% } %><% } -%><% } -%> 24 | <% if $selinux_enabled { %> --selinux-enabled=<%= $selinux_enabled %><% } -%> 25 | <% if $socket_group { %> -G <%= $socket_group %><% } -%> 26 | <% if $dns { %><% $dns_array.each |$address| { %> --dns <%= $address %><% } %><% } -%> 27 | <% if $dns_search { %><% $dns_search_array.each |$domain| { %> --dns-search <%= $domain %><% } %><% } -%> 28 | <% if $execdriver { %> -e <%= $execdriver %><% } -%> 29 | <% if $bip { %> --bip=<%= $bip %><% } -%> 30 | <% if $mtu { %> --mtu=<%= $mtu %><% } -%> 31 | <% $labels.each |$label| { %> --label <%= $label %><% } -%> 32 | <% if $extra_parameters { %><% $extra_parameters_array.each |$param| { %> <%= $param %><% } %><% } -%>" 33 | 34 | <% if $proxy { %>export http_proxy='<%= $proxy %>' 35 | export https_proxy='<%= $proxy %>'<% } %> 36 | <% if $no_proxy { %>export no_proxy='<%= $no_proxy %>'<% } %> 37 | # This is also a handy place to tweak where Docker's temporary files go. 38 | export TMPDIR="<%= $tmp_dir %>" 39 | <% if $shell_values { %><% $shell_values_array.each |$param| { %> 40 | <%= $param %><% } %><% } -%> 41 | -------------------------------------------------------------------------------- /templates/etc/sysconfig/docker.systemd.epp: -------------------------------------------------------------------------------- 1 | # This file is managed by Puppet and local changes 2 | # may be overwritten 3 | 4 | OPTIONS="<% if $root_dir { %><%= $root_dir_flag %> <%= $root_dir %><% } -%> 5 | <% if $tcp_bind { %><% $tcp_bind_array.each |$param| { %> -H <%= $param %><% } %><% } -%> 6 | <% if $tls_enable { %> --tls<% if $tls_verify { %> --tlsverify<% } %> --tlscacert=<%= $tls_cacert %> --tlscert=<%= $tls_cert %> --tlskey=<%= $tls_key %><% } -%> 7 | <% if $socket_bind { %> -H <%= $socket_bind %><% } -%> 8 | --ip-forward=<%= $ip_forward -%> 9 | --iptables=<%= $iptables -%> 10 | --ip-masq=<%= $ip_masq -%> 11 | <% if $icc { %> --icc=<%= $icc %><% } -%> 12 | <% if type($registry_mirror, 'generalized') == String { %> --registry-mirror=<%= $registry_mirror %><% } -%> 13 | <% if String(type($registry_mirror, 'generalized')).index('Array') == 0 { %><% $registry_mirror.each |$param| { %> --registry-mirror=<%= $param %><% } %><% } -%> 14 | <% if $fixed_cidr { %> --fixed-cidr <%= $fixed_cidr %><% } -%> 15 | <% if $default_gateway { %> --default-gateway <%= $default_gateway %><% } -%> 16 | <% if $ipv6 { %> --ipv6<% } -%> 17 | <% if $ipv6_cidr { %> --fixed-cidr-v6 <%= $ipv6_cidr %><% } -%> 18 | <% if $default_gateway_ipv6 { %> --default-gateway-v6 <%= $default_gateway_ipv6 %><% } -%> 19 | <% if $bridge { %> --bridge <%= $bridge %><% } -%> 20 | <% if $log_level { %> -l <%= $log_level %><% } -%> 21 | <% if $log_driver { %> --log-driver <%= $log_driver %><% } -%> 22 | <% if $log_driver { %><% if $log_opt { %><% $log_opt.each |$param| { %> --log-opt <%= $param %><% } %><% } -%><% } -%> 23 | <% if $selinux_enabled { %> --selinux-enabled=<%= $selinux_enabled %><% } -%> 24 | <% if $socket_group { %> -G <%= $socket_group %><% } -%> 25 | <% if $dns { %><% $dns_array.each |$address| { %> --dns <%= $address %><% } %><% } -%> 26 | <% if $dns_search { %><% $dns_search_array.each |$domain| { %> --dns-search <%= $domain %><% } %><% } -%> 27 | <% if $execdriver { %> -e <%= $execdriver %><% } -%> 28 | <% if $bip { %> --bip=<%= $bip %><% } -%> 29 | <% if $mtu { %> --mtu=<%= $mtu %><% } -%> 30 | <% if $labels { %><% $labels_array.each |$label| { %> --label <%= $label %><% } %><% } -%> 31 | <% if $extra_parameters { %><% $extra_parameters_array.each |$param| { %> <%= $param %><% } %><% } -%>" 32 | 33 | <% if $proxy { %>http_proxy='<%= $proxy %>' 34 | https_proxy='<%= $proxy %>'<% } %> 35 | <% if $no_proxy { %>no_proxy='<%= $no_proxy %>'<% } %> 36 | # This is also a handy place to tweak where Docker's temporary files go. 37 | <% if $tmp_dir_config { %>TMPDIR="<%= $tmp_dir %>"<% }else { %># TMPDIR="<%= $tmp_dir %>"<% } %> 38 | <% if $shell_values { %><% $shell_values_array.each |$param| { %> <%= $param %><% } %><% } -%> 39 | -------------------------------------------------------------------------------- /templates/etc/systemd/system/docker-run.epp: -------------------------------------------------------------------------------- 1 | <%- 2 | $depend_services = $depend_services_array.map |$s| { if $s =~ /\.[a-z]+$/ { $s }else { "${s}.service" } } 3 | $after = $sanitised_after_array.map |$s| { "${service_prefix}${s}.service" } + 4 | $sanitised_depends_array.map |$s| { "${service_prefix}${s}.service"} + 5 | $depend_services 6 | $wants = $sanitised_after_array.map |$a| { "${service_prefix}${a}.service" } 7 | $requires = $sanitised_depends_array.map |$d| { "${service_prefix}${d}.service" } + 8 | $depend_services 9 | -%> 10 | # This file is managed by Puppet and local changes 11 | # may be overwritten 12 | 13 | [Unit] 14 | Description=Daemon for <%= $title %> 15 | After=<%= $after.unique.join(" ") %> 16 | Wants=<%= $wants.unique.join(" ") %> 17 | Requires=<%= $requires.unique.join(" ") %> 18 | <%- if $have_systemd_v230 { -%> 19 | StartLimitIntervalSec=20 20 | StartLimitBurst=3 21 | <% } -%> 22 | <%- if $extra_systemd_parameters['Unit'] { -%> 23 | <%- $extra_systemd_parameters['Unit'].each |$key, $value| { %> 24 | <%= $key %>=<%= $value %> 25 | <%- } -%> 26 | <% } -%> 27 | 28 | [Service] 29 | Restart=<%= $systemd_restart %> 30 | <%- unless $have_systemd_v230 { -%> 31 | StartLimitInterval=20 32 | StartLimitBurst=3 33 | <% } -%> 34 | TimeoutStartSec=0 35 | RestartSec=5 36 | Environment="HOME=/root" 37 | <%- if $_syslog_identifier { -%> 38 | SyslogIdentifier=<%= $_syslog_identifier %> 39 | <% } -%> 40 | <%- if $syslog_facility { -%> 41 | SyslogFacility=<%= $syslog_facility %> 42 | <% } -%> 43 | ExecStart=/usr/local/bin/docker-run-<%= $sanitised_title %>-start.sh 44 | ExecStop=-/usr/local/bin/docker-run-<%= $sanitised_title %>-stop.sh 45 | <%- if $remain_after_exit { %> 46 | RemainAfterExit=<%= $remain_after_exit %> 47 | <% } -%> 48 | <%- if $extra_systemd_parameters['Service'] { -%> 49 | <%- $extra_systemd_parameters['Service'].each |$key, $value| { -%> 50 | <%= $key %>=<%= $value %> 51 | <%- } -%> 52 | <% } -%> 53 | 54 | [Install] 55 | WantedBy=multi-user.target 56 | <%- if $service_name { -%> 57 | WantedBy=<%= $service_name %>.service 58 | <% } -%> 59 | <%- if $extra_systemd_parameters['Install'] { -%> 60 | <%- $extra_systemd_parameters['Install'].each |$key, $value| { -%> 61 | <%= $key %>=<%= $value %> 62 | <%- } -%> 63 | <% } -%> 64 | -------------------------------------------------------------------------------- /templates/etc/systemd/system/docker.service.d/service-overrides-debian.conf.epp: -------------------------------------------------------------------------------- 1 | <% if $service_after_override { -%> 2 | [Unit] 3 | After=<%= $service_after_override %> 4 | 5 | <% } -%> 6 | [Service] 7 | EnvironmentFile=-/etc/default/docker 8 | EnvironmentFile=-/etc/default/docker-storage 9 | ExecStart= 10 | ExecStart=/usr/bin/<%= $docker_start_command %> $OPTIONS \ 11 | $DOCKER_STORAGE_OPTIONS 12 | -------------------------------------------------------------------------------- /templates/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.epp: -------------------------------------------------------------------------------- 1 | <% if $service_after_override { -%> 2 | [Unit] 3 | After=<%= $service_after_override %> 4 | 5 | <% } -%> 6 | [Service] 7 | EnvironmentFile=-/etc/sysconfig/docker 8 | EnvironmentFile=-/etc/sysconfig/docker-storage 9 | EnvironmentFile=-/etc/sysconfig/docker-network 10 | <% if $daemon_environment_files { %><% $daemon_environment_files.each |$param| { %>EnvironmentFile=-<%= $param %> 11 | <% } %><% } -%> 12 | ExecStart= 13 | ExecStart=/usr/bin/<%= $docker_start_command %> $OPTIONS \ 14 | $DOCKER_STORAGE_OPTIONS \ 15 | $DOCKER_NETWORK_OPTIONS \ 16 | $BLOCK_REGISTRY \ 17 | $INSECURE_REGISTRY 18 | -------------------------------------------------------------------------------- /templates/etc/systemd/system/docker.socket.d/socket-overrides.conf.epp: -------------------------------------------------------------------------------- 1 | [Socket] 2 | SocketGroup=<%= $socket_group %> 3 | -------------------------------------------------------------------------------- /templates/update_docker_image.sh.epp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Pulls a docker image. 4 | # Returns 0 if there a change. 5 | # Returns 2 if there is no change. 6 | # Returns 3 if something when wrong. 7 | # 8 | DOCKER_IMAGE=$1 9 | 10 | BEFORE=$(docker inspect --type image --format='{{.Id}}' ${DOCKER_IMAGE} 2>/dev/null) 11 | <%= $docker_command %> pull ${DOCKER_IMAGE} 12 | AFTER=$(docker inspect --type image --format='{{.Id}}' ${DOCKER_IMAGE} 2>/dev/null) 13 | 14 | if [[ -z $AFTER ]]; then 15 | echo "Docker image ${DOCKER_IMAGE} failed to pull!" 16 | exit 3 17 | elif [[ $BEFORE == $AFTER ]]; then 18 | echo "No updates to ${DOCKER_IMAGE} available. Currently on ${AFTER}." 19 | exit 2 20 | else 21 | echo "${DOCKER_IMAGE} updated. Changed from ${BEFORE} to ${AFTER}." 22 | exit 0 23 | fi 24 | -------------------------------------------------------------------------------- /templates/usr/local/bin/docker-run.sh.epp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | <%= $script %> 4 | 5 | exit $? 6 | -------------------------------------------------------------------------------- /templates/windows/check_docker.ps1.epp: -------------------------------------------------------------------------------- 1 | # this file checks the status of the Windows Docker package using the DockerProvider powershell provider 2 | $dockerProviderName="DockerProvider" 3 | 4 | Write-Information "Checking Docker package." 5 | $package=Get-Package <%= $docker_ee_package_name %> -ProviderName $dockerProviderName -ErrorAction Ignore 6 | if ($package -ne $null) { 7 | Exit 1 8 | } 9 | 10 | $service = Get-Service "docker" -ErrorAction Ignore 11 | if ($service -ne $null) { 12 | exit 1 13 | } 14 | 15 | if (Test-Path -Path "$env:ProgramFiles\docker") { 16 | exit 1 17 | } 18 | 19 | exit 0 20 | -------------------------------------------------------------------------------- /templates/windows/check_docker_url.ps1.epp: -------------------------------------------------------------------------------- 1 | $dockerLocation = Join-Path $env:TEMP "docker.zip" 2 | 3 | if ((test-path $dockerLocation)) 4 | { 5 | $localModified = (Get-Item $dockerLocation).LastWriteTime 6 | $webRequest = [System.Net.HttpWebRequest]::Create("<%= $docker_download_url %>"); 7 | $webRequest.Method = "HEAD"; 8 | $webResponse = $webRequest.GetResponse() 9 | $remoteLastModified = ($webResponse.LastModified) -as [DateTime] 10 | $webResponse.Close() 11 | 12 | if ($remoteLastModified -gt $localModified) 13 | { 14 | exit 1 15 | } 16 | else 17 | { 18 | exit 0 19 | } 20 | } 21 | 22 | exit 1 23 | -------------------------------------------------------------------------------- /templates/windows/check_hash.ps1.epp: -------------------------------------------------------------------------------- 1 | #file computes the 512SHA for a given string and writes it to a file 2 | 3 | $String = $env:docker_auth 4 | $HashName = "SHA512" 5 | $StringBuilder = New-Object System.Text.StringBuilder 6 | [System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|%{ 7 | [Void]$StringBuilder.Append($_.ToString("x2")) 8 | } 9 | 10 | if([System.IO.File]::Exists("<%= $passfile %>")){ 11 | $CurrentContent = Get-Content -Path "<%= $passfile %>" 12 | if($CurrentContent -eq $StringBuilder.ToString()){ 13 | exit 0 14 | } 15 | } 16 | 17 | exit 1 18 | -------------------------------------------------------------------------------- /templates/windows/check_powershell_provider.ps1.epp: -------------------------------------------------------------------------------- 1 | # this file checks the status of the Windows Docker package using the DockerProvider powershell provider 2 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 3 | $dockerProviderName="DockerProvider" 4 | 5 | Write-Information "Checking Package Provider" 6 | $module = Get-PackageProvider NuGet -ErrorAction SilentlyContinue 7 | If ($module -eq $null) { 8 | Write-Error "NuGet PackagePrivider is not installed." 9 | Exit 1 10 | } 11 | 12 | <% if $nuget_package_provider_version { -%> 13 | Write-Information "Checking Package provider version" 14 | if ($module.Version.ToString() -ne "<%= $nuget_package_provider_version %>" ) { 15 | Write-Error "Incorrect Microsoft Nuget provider version installed" 16 | Exit 1 17 | } 18 | <% } -%> 19 | 20 | Write-Information "Checking Docker Provider" 21 | $provider = Get-Module -ListAvailable -Name $dockerProviderName -ErrorAction SilentlyContinue 22 | If ($provider -eq $null) { 23 | Write-Error "Docker Microsoft Docker provider is not installed." 24 | Exit 1 25 | } 26 | 27 | <% if $docker_msft_provider_version { -%> 28 | Write-Information "Checking Docker provider version" 29 | if ($provider.Version.ToString() -ne "<%= $docker_msft_provider_version %>" ) { 30 | Write-Error "Incorrect Microsoft Docker Provider version installed." 31 | Exit 1 32 | } 33 | <% } -%> 34 | 35 | Write-Information "Checking Docker package." 36 | $package=Get-Package <%= $docker_ee_package_name %> -ProviderName $dockerProviderName -ErrorAction SilentlyContinue 37 | If ($package -eq $null) { 38 | Write-Error "Docker package is not installed." 39 | Exit 1 40 | } 41 | 42 | <% if $version { -%> 43 | Write-Information "Checking Docker package version" 44 | if ($package.Version.ToString() -notmatch "<%= $version %>"){ 45 | Write-Error "Incorrect Docker package version installed." 46 | Exit 1 47 | } 48 | <% } %> 49 | -------------------------------------------------------------------------------- /templates/windows/compute_hash.ps1.epp: -------------------------------------------------------------------------------- 1 | #file computes the 512SHA for a given string and writes it to a file 2 | 3 | $String = $env:docker_auth 4 | $HashName = "SHA512" 5 | $StringBuilder = New-Object System.Text.StringBuilder 6 | [System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|%{ 7 | [Void]$StringBuilder.Append($_.ToString("x2")) 8 | } 9 | 10 | $StringBuilder.ToString() | Out-File <%= $passfile %> 11 | -------------------------------------------------------------------------------- /templates/windows/config/daemon.json.epp: -------------------------------------------------------------------------------- 1 | { 2 | <% if $dns { %> "dns": <%= $dns_array.to_json %>,<% } -%> 3 | <% if $dns_search { %> "dns-search": <%= $dns_search_array.to_json %>,<% } -%> 4 | <% if $log_driver { %> "log-driver": "<%= $log_driver %>", <% } -%> 5 | <% if $mtu { %> "mtu": <%= $mtu %>,<% } -%> 6 | <% if $tcp_bind { %> "hosts": <%= $tcp_bind_array.to_json %>,<% } -%> 7 | <% if $log_level { %> "log-level": "<%= $log_level %>",<% } -%> 8 | <% if $tls_enable { %> "tlsverify": true, 9 | "tlscacert": "<%= $tls_cacert %>", 10 | "tlscert": "<%= $tls_cert %>", 11 | "tlskey": "<%= $tls_key %>", 12 | <% } -%> 13 | <% if $socket_group { %>"group": "<%= $socket_group %>",<% } -%> 14 | <% if $bridge { %>"bridge": "<%= $bridge %>",<% } -%> 15 | <% if $fixed_cidr { %>"fixed-cidr": "<%= $fixed_cidr %>",<% } -%> 16 | <% if type($registry_mirror, 'generalized') == String { %>"registry-mirrors": ["<%= $registry_mirror %>"], <% } -%> 17 | <% if String(type($registry_mirror, 'generalized')).index('Array') == 0 { %>"registry-mirrors": ["<%= $registry_mirror.join('", "') %>"], <% } -%> 18 | <% if $extra_parameters { %><% $extra_parameters_array.each |$param| { %> 19 | <%= $param %> ,<% } %> 20 | <% } -%> 21 | <% if $root_dir { %>"data-root": "<%= $root_dir %>",<% } -%> 22 | "labels": <%= $labels_array.to_json %> 23 | } 24 | -------------------------------------------------------------------------------- /templates/windows/download_docker.ps1.epp: -------------------------------------------------------------------------------- 1 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 2 | $dockerLocation = Join-Path $env:TEMP "docker.zip" 3 | 4 | Invoke-webrequest -UseBasicparsing -Outfile $dockerLocation "<%= $docker_download_url %>" 5 | 6 | $cleanInstall = $false 7 | 8 | $service = Get-Service "docker" -ErrorAction Ignore 9 | if ( -not $service ) { 10 | $cleanInstall = $true 11 | } elseif ( $service.Status -ne [ServiceProcess.ServiceControllerStatus]::Stopped ) { 12 | $timeSpan = New-Timespan -Seconds 60 13 | try { 14 | $service.Stop() 15 | $service.WaitForStatus([ServiceProcess.ServiceControllerStatus]::Stopped, $timeSpan) 16 | } 17 | catch [Management.Automation.MethodInvocationException],[ServiceProcess.TimeoutException] { 18 | Write-Error "Failed to stop docker service" 19 | exit 1 20 | } 21 | } 22 | 23 | # Extract the archive. 24 | Expand-Archive -Force $dockerLocation -DestinationPath $Env:ProgramFiles 25 | 26 | # Install Docker. This will require rebooting. 27 | $null = Install-WindowsFeature containers 28 | 29 | if ($cleanInstall) { 30 | # Add Docker to the path for the current session. 31 | $env:path += ";$env:ProgramFiles\docker" 32 | 33 | # Optionally, modify PATH to persist across sessions. 34 | $newPath = "$env:ProgramFiles\docker;" + [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::Machine) 35 | 36 | [Environment]::SetEnvironmentVariable("PATH", $newPath, [EnvironmentVariableTarget]::Machine) 37 | 38 | # Register the Docker daemon as a service. 39 | dockerd --register-service 40 | } 41 | -------------------------------------------------------------------------------- /templates/windows/download_docker_compose.ps1.epp: -------------------------------------------------------------------------------- 1 | try { 2 | $WebClient = New-Object System.Net.WebClient 3 | <%if $proxy { %> 4 | $uri = New-Object Uri("<%= $proxy %>") 5 | if ($uri.UserInfo -eq $null) { 6 | $WebProxy = New-Object System.Net.WebProxy("<%= $proxy %>",$true) 7 | $WebClient.Proxy = $WebProxy 8 | } 9 | else { 10 | $user,$password = $uri.UserInfo -split (':') 11 | $proxyAddress = $uri.Scheme + "://" + $uri.Host + ":" + $uri.Port + $uri.PathAndQuery 12 | $WebProxy = New-Object System.Net.WebProxy($uri,$true) 13 | $WebClient.Proxy = $WebProxy 14 | $WebClient.Proxy.Credentials = New-Object System.Net.NetworkCredential($user, $password) 15 | } 16 | <% } %> 17 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 18 | $WebClient.DownloadFile("<%= $docker_compose_url %>","<%= $docker_compose_location_versioned %>") 19 | } 20 | catch { 21 | exit 1 22 | } 23 | exit 0 24 | -------------------------------------------------------------------------------- /templates/windows/download_docker_machine.ps1.epp: -------------------------------------------------------------------------------- 1 | try { 2 | $WebClient = New-Object System.Net.WebClient 3 | <%if $proxy { %> 4 | $uri = New-Object Uri("<%= $proxy %>") 5 | if ($uri.UserInfo -eq $null) { 6 | $WebProxy = New-Object System.Net.WebProxy("<%= $proxy %>",$true) 7 | $WebClient.Proxy = $WebProxy 8 | } 9 | else { 10 | $user,$password = $uri.UserInfo -split (':') 11 | $proxyAddress = $uri.Scheme + "://" + $uri.Host + ":" + $uri.Port + $uri.PathAndQuery 12 | $WebProxy = New-Object System.Net.WebProxy($uri,$true) 13 | $WebClient.Proxy = $WebProxy 14 | $WebClient.Proxy.Credentials = New-Object System.Net.NetworkCredential($user, $password) 15 | } 16 | <% } %> 17 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 18 | $WebClient.DownloadFile("<%= $docker_machine_url %>","<%= $docker_machine_location_versioned %>") 19 | } 20 | catch { 21 | exit 1 22 | } 23 | exit 0 24 | -------------------------------------------------------------------------------- /templates/windows/install_powershell_provider.ps1.epp: -------------------------------------------------------------------------------- 1 | # this file install the Windows Docker package using the DockerProvider powershell provider 2 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 3 | $dockerProviderName="DockerProvider" 4 | 5 | Write-Information "Installing Package Provider" 6 | $module = Install-PackageProvider NuGet -Force <% if $nuget_package_provider_version { %><%= "-RequiredVersion ${nuget_package_provider_version}" %><% } %> 7 | 8 | If ($module -eq $null) { 9 | Write-Error "Failed to install NuGet Package Provider" 10 | Exit 1 11 | } 12 | 13 | Write-Information "Installing Docker Provider" 14 | Install-Module $dockerProviderName -Force <% if $docker_msft_provider_version { %><%= "-RequiredVersion ${docker_msft_provider_version}" %><% } %> 15 | 16 | $provider = Get-Module -ListAvailable -Name $dockerProviderName 17 | If ($provider -eq $null) { 18 | Write-Error "Failed to install Docker Microsoft Provider" 19 | Exit 1 20 | } 21 | 22 | Write-Information "Installing Docker Package" 23 | $package=Install-Package Docker -ProviderName $dockerProviderName -Force <% if $version { %><%= "-RequiredVersion ${version}" %><% } %> 24 | 25 | If ($package -eq $null) { 26 | Write-Error "Failed to install Docker Package" 27 | Exit 1 28 | } 29 | -------------------------------------------------------------------------------- /templates/windows/remove_docker.ps1.epp: -------------------------------------------------------------------------------- 1 | # this file install the Windows Docker package using the DockerProvider powershell provider 2 | $dockerProviderName="DockerProvider" 3 | 4 | $package=Get-Package <%= $docker_ee_package_name %> -ProviderName $dockerProviderName -ErrorAction Ignore 5 | If ($package -ne $null) { 6 | Write-Information "Uninstalling Docker Package" 7 | $package=Uninstall-Package <%= $docker_ee_package_name %> -ProviderName $dockerProviderName -Force 8 | <% if $version { -%> 9 | -RequiredVersion <%= $version %> 10 | <% } -%> 11 | If ($package -eq $null) { 12 | Write-Error "Failed to uninstall Docker Package" 13 | Exit 1 14 | } 15 | } 16 | 17 | $provider = Get-Module -ListAvailable -Name $dockerProviderName -ErrorAction Ignore 18 | If ($provider -ne $null) { 19 | Write-Information "Uninstalling Docker Provider" 20 | Uninstall-Module $dockerProviderName -Force 21 | 22 | $provider = Get-Module -ListAvailable -Name $dockerProviderName -ErrorAction Ignore 23 | If ($provider -ne $null) { 24 | Write-Error "Failed to uninstall Docker Microsoft Provider" 25 | Exit 1 26 | } 27 | } 28 | 29 | $service = Get-Service "docker" -ErrorAction Ignore 30 | if ($service -ne $null) { 31 | if ( $service.Status -ne [ServiceProcess.ServiceControllerStatus]::Stopped ) { 32 | $timeSpan = New-Object Timespan 0,0,60 33 | try { 34 | $service.Stop() 35 | $service.WaitForStatus([ServiceProcess.ServiceControllerStatus]::Stopped, 60) 36 | } 37 | catch [Management.Automation.MethodInvocationException],[ServiceProcess.TimeoutException] { 38 | Write-Error "Failed to stop docker service" 39 | exit 1 40 | } 41 | } 42 | 43 | sc.exe delete "docker" 44 | } 45 | 46 | if (Test-Path -Path "$env:ProgramFiles\docker") { 47 | Remove-Item "$env:ProgramFiles\docker" -Recurse -Force 48 | } 49 | -------------------------------------------------------------------------------- /templates/windows/update_docker_image.ps1.epp: -------------------------------------------------------------------------------- 1 | # Pulls a docker image. 2 | # Returns 0 if there a change. 3 | # Returns 2 if there is no change. 4 | # Returns 3 if something when wrong. 5 | # 6 | 7 | param 8 | ( 9 | [string]$DockerImage 10 | ) 11 | 12 | Write-Information "Before - Looking for image" 13 | $before=$(& <%= $docker_command %> inspect --type image --format='{{.Id}}' ${DockerImage} 2>$null) 14 | Write-Information "Pulling image" 15 | & <%= $docker_command %> pull ${DockerImage} 16 | Write-Information "Inspecting image" 17 | $after=$(& <%= $docker_command %> inspect --type image --format='{{.Id}}' ${DockerImage} 2>$null) 18 | If (!$after) { 19 | Write-Information "Docker image ${DockerImage} failed to pull!" 20 | Exit 3 21 | } ElseIf ($after -eq $before) { 22 | Write-Information "No updates to ${DockerImage} available. Currently on ${after}." 23 | Exit 2 24 | } Else { 25 | Write-Information "${DockerImage} updated. Changed from ${before} to ${after}." 26 | Exit 0 27 | } 28 | --------------------------------------------------------------------------------