├── .editorconfig ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS ├── lock.yml └── workflows │ ├── ci.yml │ └── stale.yml ├── .gitignore ├── .markdownlint-cli2.yaml ├── .markdownlint.json ├── .mdlrc ├── .overcommit.yml ├── .rubocop.yml ├── .vscode └── extensions.json ├── .yamllint ├── Berksfile ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dangerfile ├── Guardfile ├── LICENSE ├── README.md ├── TESTING.md ├── chefignore ├── documentation ├── .gitkeep ├── haproxy_acl.md ├── haproxy_backend.md ├── haproxy_cache.md ├── haproxy_config_defaults.md ├── haproxy_config_global.md ├── haproxy_fastcgi.md ├── haproxy_frontend.md ├── haproxy_install.md ├── haproxy_listen.md ├── haproxy_mailer.md ├── haproxy_peer.md ├── haproxy_resolver.md ├── haproxy_service.md ├── haproxy_use_backend.md ├── haproxy_userlist.md ├── partial_config_file.md └── partial_extra_options.md ├── files └── haproxy-default ├── kitchen.dokken.yml ├── kitchen.exec.yml ├── kitchen.global.yml ├── kitchen.yml ├── libraries ├── helpers.rb ├── resource.rb └── template.rb ├── metadata.rb ├── renovate.json ├── resources ├── acl.rb ├── backend.rb ├── cache.rb ├── config_defaults.rb ├── config_global.rb ├── fastcgi.rb ├── frontend.rb ├── install.rb ├── listen.rb ├── mailer.rb ├── partial │ ├── _config_file.rb │ └── _extra_options.rb ├── peer.rb ├── resolver.rb ├── service.rb ├── use_backend.rb └── userlist.rb ├── spec ├── spec_helper.rb └── unit │ └── recipes │ ├── cache_spec.rb │ ├── defaults_spec.rb │ ├── fastcgi_spec.rb │ ├── frontend_backend_spec.rb │ ├── global_spec.rb │ ├── install_spec.rb │ ├── listen_spec.rb │ ├── mailer_spec.rb │ └── peer_spec.rb ├── templates └── default │ └── haproxy.cfg.erb └── test ├── cookbooks └── test │ ├── files │ └── default │ │ └── example.com.pem │ ├── metadata.rb │ ├── recipes │ ├── config_2.rb │ ├── config_3.rb │ ├── config_acl.rb │ ├── config_array.rb │ ├── config_backend_search.rb │ ├── config_custom_template.rb │ ├── config_fastcgi.rb │ ├── config_resolver.rb │ ├── config_ssl_redirect.rb │ ├── package.rb │ ├── source.rb │ ├── source_24.rb │ ├── source_26.rb │ ├── source_28.rb │ ├── source_29.rb │ ├── source_lua.rb │ └── source_openssl.rb │ └── templates │ └── default │ └── custom-template.cfg.erb └── integration ├── common ├── controls │ └── common_spec.rb └── inspec.yml ├── config_2 ├── controls │ └── config_spec.rb └── inspec.yml ├── config_3 ├── controls │ └── config_spec.rb └── inspec.yml ├── config_acl ├── controls │ └── config_spec.rb └── inspec.yml ├── config_array ├── controls │ └── config_spec.rb └── inspec.yml ├── config_backend_search ├── controls │ └── config_backend_search_spec.rb └── inspec.yml ├── config_custom_template ├── controls │ └── template_spec.rb └── inspec.yml ├── config_fastcgi ├── controls │ └── fast_cgi_spec.rb └── inspec.yml ├── config_resolver ├── controls │ └── resolver_spec.rb └── inspec.yml ├── config_ssl_redirect ├── controls │ └── ssl_redirect_spec.rb └── inspec.yml ├── nodes ├── be-1.json └── be-2.json ├── package ├── controls │ └── package_spec.rb └── inspec.yml ├── source-default ├── controls │ └── source_spec.rb └── inspec.yml ├── source_2.4 ├── controls │ └── source_spec.rb └── inspec.yml ├── source_2.6 ├── controls │ └── source_spec.rb └── inspec.yml ├── source_2.8 ├── controls │ └── source_spec.rb └── inspec.yml ├── source_2.9 ├── controls │ └── source_spec.rb └── inspec.yml ├── source_lua ├── controls │ └── lua_spec.rb └── inspec.yml └── source_openssl ├── controls └── openssl_spec.rb └── inspec.yml /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root=true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # 2 space indentation 12 | indent_style = space 13 | indent_size = 2 14 | 15 | # Avoid issues parsing cookbook files later 16 | charset = utf-8 17 | 18 | # Avoid cookstyle warnings 19 | trim_trailing_whitespace = true 20 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use chefworkstation 2 | export KITCHEN_GLOBAL_YAML=kitchen.global.yml 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sous-chefs/maintainers 2 | -------------------------------------------------------------------------------- /.github/lock.yml: -------------------------------------------------------------------------------- 1 | --- 2 | daysUntilLock: 365 3 | exemptLabels: [] 4 | lockLabel: false 5 | lockComment: > 6 | This thread has been automatically locked since there has not been 7 | any recent activity after it was closed. Please open a new issue for 8 | related bugs. 9 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: ci 3 | 4 | "on": 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | lint-unit: 12 | uses: sous-chefs/.github/.github/workflows/lint-unit.yml@3.1.1 13 | permissions: 14 | actions: write 15 | checks: write 16 | pull-requests: write 17 | statuses: write 18 | issues: write 19 | 20 | integration: 21 | needs: lint-unit 22 | runs-on: ubuntu-latest 23 | strategy: 24 | matrix: 25 | os: 26 | - "debian-11" 27 | - "debian-12" 28 | - "ubuntu-2004" 29 | - "ubuntu-2204" 30 | - "centos-stream-8" 31 | - "centos-stream-9" 32 | - "fedora-latest" 33 | suite: 34 | - config-2 35 | - config-3 36 | - config-acl 37 | - config-array 38 | - config-backend-search 39 | - config-custom-template 40 | - config-fastcgi 41 | - config-resolver 42 | - config-ssl-redirect 43 | - "package" 44 | - "source-24" 45 | - "source-26" 46 | - "source-28" 47 | - "source-29" 48 | - "source-lua" 49 | - "source-default" 50 | # - "source-openssl" 51 | # OpenSSSL libraries are not currently compiling correctly 52 | # see https://github.com/sous-chefs/haproxy/issues/503 53 | fail-fast: false 54 | 55 | steps: 56 | - name: Check out code 57 | uses: actions/checkout@v4 # v4 58 | - name: Install Chef 59 | uses: actionshub/chef-install@main 60 | - name: Dokken 61 | uses: actionshub/test-kitchen@main 62 | env: 63 | CHEF_LICENSE: accept-no-persist 64 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 65 | with: 66 | suite: ${{ matrix.suite }} 67 | os: ${{ matrix.os }} 68 | 69 | integration-amazonlinux: 70 | needs: lint-unit 71 | runs-on: ubuntu-24.04 72 | strategy: 73 | matrix: 74 | os: 75 | - "amazonlinux-2023" 76 | suite: 77 | - "package" 78 | - "source-24" 79 | - "source-26" 80 | - "source-28" 81 | - "source-29" 82 | - "source-default" 83 | fail-fast: false 84 | 85 | steps: 86 | - name: Check out code 87 | uses: actions/checkout@v4 # v4 88 | - name: Install Chef 89 | uses: actionshub/chef-install@3.0.0 90 | - name: Dokken 91 | uses: actionshub/test-kitchen@3.0.0 92 | env: 93 | CHEF_LICENSE: accept-no-persist 94 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 95 | with: 96 | suite: ${{ matrix.suite }} 97 | os: ${{ matrix.os }} 98 | 99 | lua_test: 100 | needs: lint-unit 101 | runs-on: ubuntu-latest 102 | strategy: 103 | matrix: 104 | os: 105 | - "centos-7" 106 | suite: 107 | - "source-lua" 108 | fail-fast: false 109 | 110 | steps: 111 | - name: Check out code 112 | uses: actions/checkout@v4 # v4 113 | - name: Install Chef 114 | uses: actionshub/chef-install@3.0.0 115 | - name: Dokken 116 | uses: actionshub/test-kitchen@3.0.0 117 | env: 118 | CHEF_LICENSE: accept-no-persist 119 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 120 | with: 121 | suite: ${{ matrix.suite }} 122 | os: ${{ matrix.os }} 123 | 124 | configtest: 125 | needs: lint-unit 126 | runs-on: ubuntu-latest 127 | strategy: 128 | matrix: 129 | os: 130 | - "centos-7" 131 | - "centos-stream-8" 132 | suite: 133 | - "config-2" 134 | - "config-3" 135 | - "config-backend-search" 136 | - "config-acl" 137 | - "config-resolver" 138 | - "config-ssl-redirect" 139 | - "config-custom-template" 140 | - "config-custom-template" 141 | - "config-array" 142 | - "config-fastcgi" 143 | fail-fast: false 144 | 145 | steps: 146 | - name: Check out code 147 | uses: actions/checkout@v4 # v4 148 | - name: Install Chef 149 | uses: actionshub/chef-install@3.0.0 150 | - name: Dokken 151 | uses: actionshub/test-kitchen@3.0.0 152 | env: 153 | CHEF_LICENSE: accept-no-persist 154 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 155 | with: 156 | suite: ${{ matrix.suite }} 157 | os: ${{ matrix.os }} 158 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mark stale issues and pull requests 3 | 4 | "on": 5 | schedule: [cron: "0 0 * * *"] 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v9 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | close-issue-message: > 15 | Closing due to inactivity. 16 | If this is still an issue please reopen or open another issue. 17 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 18 | Thanks, Sous-Chefs. 19 | days-before-close: 7 20 | days-before-stale: 365 21 | stale-issue-message: > 22 | Marking stale due to inactivity. 23 | Remove stale label or comment or this will be closed in 7 days. 24 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 25 | Thanks, Sous-Chefs. 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | .config 3 | InstalledFiles 4 | pkg 5 | test/tmp 6 | test/version_tmp 7 | tmp 8 | _Store 9 | *~ 10 | *# 11 | .#* 12 | \#*# 13 | *.un~ 14 | *.tmp 15 | *.bk 16 | *.bkup 17 | 18 | # editor files 19 | .idea 20 | .*.sw[a-z] 21 | 22 | # ruby/bundler/rspec files 23 | .ruby-version 24 | .ruby-gemset 25 | .rvmrc 26 | Gemfile.lock 27 | .bundle 28 | *.gem 29 | coverage 30 | spec/reports 31 | 32 | # YARD / rdoc artifacts 33 | .yardoc 34 | _yardoc 35 | doc/ 36 | rdoc 37 | 38 | # chef infra stuff 39 | Berksfile.lock 40 | .kitchen 41 | kitchen.local.yml 42 | vendor/ 43 | .coverage/ 44 | .zero-knife.rb 45 | Policyfile.lock.json 46 | 47 | # vagrant stuff 48 | .vagrant/ 49 | .vagrant.d/ 50 | -------------------------------------------------------------------------------- /.markdownlint-cli2.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | ul-indent: false # MD007 3 | line-length: false # MD013 4 | no-duplicate-heading: false # MD024 5 | reference-links-images: false # MD052 6 | ignores: 7 | - .github/copilot-instructions.md 8 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD024": { 3 | "siblings_only": true 4 | }, 5 | "MD013":false 6 | } 7 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | rules "~MD013", "~MD024" 2 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | PreCommit: 3 | TrailingWhitespace: 4 | enabled: true 5 | YamlLint: 6 | enabled: true 7 | required_executable: "yamllint" 8 | ChefSpec: 9 | enabled: true 10 | required_executable: "chef" 11 | command: ["chef", "exec", "rspec"] 12 | Cookstyle: 13 | enabled: true 14 | required_executable: "cookstyle" 15 | command: ["cookstyle"] 16 | MarkdownLint: 17 | enabled: false 18 | required_executable: "npx" 19 | command: ["npx", "markdownlint-cli2", "'**/*.md'"] 20 | include: ["**/*.md"] 21 | 22 | CommitMsg: 23 | HardTabs: 24 | enabled: true 25 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - cookstyle 3 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "chef-software.chef", 4 | "rebornix.ruby", 5 | "editorconfig.editorconfig", 6 | "DavidAnson.vscode-markdownlint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | rules: 4 | line-length: 5 | max: 256 6 | level: warning 7 | document-start: disable 8 | braces: 9 | forbid: false 10 | min-spaces-inside: 0 11 | max-spaces-inside: 1 12 | min-spaces-inside-empty: -1 13 | max-spaces-inside-empty: -1 14 | comments: 15 | min-spaces-from-content: 1 16 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.chef.io' 2 | 3 | metadata 4 | 5 | group :integration do 6 | cookbook 'test', path: 'test/cookbooks/test' 7 | end 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Guidelines 2 | 3 | This project follows the Chef Community Guidelines 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please refer to 4 | [https://github.com/chef-cookbooks/community_cookbook_documentation/blob/main/CONTRIBUTING.MD](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/main/CONTRIBUTING.MD) 5 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # Reference: http://danger.systems/reference.html 2 | 3 | # A pull request summary is required. Add a description of the pull request purpose. 4 | # Changelog must be updated for each pull request that changes code. 5 | # Warnings will be issued for: 6 | # Pull request with more than 400 lines of code changed 7 | # Pull reqest that change more than 5 lines without test changes 8 | # Failures will be issued for: 9 | # Pull request without summary 10 | # Pull requests with code changes without changelog entry 11 | 12 | def code_changes? 13 | code = %w(libraries attributes recipes resources files templates) 14 | code.each do |location| 15 | return true unless git.modified_files.grep(/#{location}/).empty? 16 | end 17 | false 18 | end 19 | 20 | def test_changes? 21 | tests = %w(spec test kitchen.yml kitchen.dokken.yml) 22 | tests.each do |location| 23 | return true unless git.modified_files.grep(/#{location}/).empty? 24 | end 25 | false 26 | end 27 | 28 | failure 'Please provide a summary of your Pull Request.' if github.pr_body.length < 10 29 | 30 | warn 'This is a big Pull Request.' if git.lines_of_code > 400 31 | 32 | warn 'This is a Table Flip.' if git.lines_of_code > 2000 33 | 34 | # Require a CHANGELOG entry for non-test changes. 35 | if !git.modified_files.include?('CHANGELOG.md') && code_changes? 36 | failure 'Please include a CHANGELOG entry.' 37 | end 38 | 39 | # Require Major Minor Patch version labels 40 | unless github.pr_labels.grep(/minor|major|patch/i) 41 | warn 'Please add a release label to this pull request' 42 | end 43 | 44 | # A sanity check for tests. 45 | if git.lines_of_code > 5 && code_changes? && !test_changes? 46 | warn 'This Pull Request is probably missing tests.' 47 | end 48 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | require "cookstyle" 2 | 3 | guard :rubocop, keep_failed: false, cli: "-r finstyle" do 4 | watch(/.+\.rb$/) { |m| m[0] } 5 | watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) } 6 | end 7 | 8 | guard "foodcritic", cookbook_paths: ".", cli: "-C -t ~FC001" do 9 | watch(%r{attributes/.+\.rb$}) 10 | watch(%r{providers/.+\.rb$}) 11 | watch(%r{recipes/.+\.rb$}) 12 | watch(%r{resources/.+\.rb$}) 13 | end 14 | 15 | spec_path = "test/unit" 16 | rspec_guard_config = { 17 | cmd: "bundle exec rspec --color --format progress --default-path=#{spec_path}", 18 | all_on_start: true, 19 | spec_paths: [spec_path], 20 | } 21 | 22 | guard "rspec", rspec_guard_config do 23 | watch(%r{^#{spec_path}/.+_spec\.rb$}) 24 | watch("#{spec_path}/spec_helper.rb") { spec_path } 25 | watch(%r{^(libraries|providers|recipes|resources)/(.+)\.rb$}) do |m| 26 | "#{spec_path}/#{m[2]}_spec.rb" 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # haproxy Cookbook 2 | 3 | [![CI State](https://github.com/sous-chefs/haproxy/workflows/ci/badge.svg)](https://github.com/sous-chefs/haproxy/actions?query=workflow%3Aci) 4 | [![Cookbook Version](https://img.shields.io/cookbook/v/haproxy.svg)](https://supermarket.chef.io/cookbooks/haproxy) 5 | [![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers) 6 | [![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors) 7 | [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) 8 | 9 | Installs and configures HAProxy. 10 | 11 | ## Maintainers 12 | 13 | This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If you’d like to know more please visit [sous-chefs.org](https://sous-chefs.org/) or come chat with us on the Chef Community Slack in [#sous-chefs](https://chefcommunity.slack.com/messages/C2V7B88SF). 14 | 15 | ## Requirements 16 | 17 | * HAProxy `stable` or `LTS` 18 | * Chef 13.9+ 19 | 20 | ### Platforms 21 | 22 | This cookbook officially supports and is tested against the following platforms: 23 | 24 | * debian: 9 & 10 25 | * ubuntu: 20.04 & 21.04 26 | * centos: 7 & 8 27 | * centos-stream: 8 28 | * fedora: latest 29 | * amazonlinux: 2 30 | 31 | PRs are welcome to add support for additional platforms. 32 | 33 | ### Examples 34 | 35 | Please check for working examples in [the test cookbook](test/cookbooks/test). 36 | 37 | ## Common Resource Features 38 | 39 | HAProxy has many configurable options available, this cookbook makes the most popular options available as resource properties. 40 | 41 | If you wish to use a HAProxy property that is not listed the `extra_options` hash is available to take in any number of additional values. 42 | 43 | For example, the ability to disable listeners is not provided out of the box. Further examples can be found in either `test/fixtures/recipes` or `spec/test/recipes`. If you have questions on how this works or would like to add more examples so it is easier to understand, please come talk to us on the [Chef Community Slack](http://community-slack.chef.io/) on the #sous-chefs channel. 44 | 45 | ```ruby 46 | haproxy_listen 'disabled' do 47 | bind '0.0.0.0:1337' 48 | mode 'http' 49 | extra_options('disabled': '') 50 | end 51 | ``` 52 | 53 | The `extra_options` hash is of `String => String` or `String => Array`. When an `Array` value is provided. The values are looped over mapping the key to each value in the config. 54 | 55 | For example: 56 | 57 | ```ruby 58 | haproxy_listen 'default' do 59 | extra_options( 60 | 'http-request' => [ 'set-header X-Public-User yes', 'del-header X-Bad-Header' ] 61 | ) 62 | end 63 | ``` 64 | 65 | Becomes: 66 | 67 | ```haproxy 68 | listen default 69 | ... 70 | http-request set-header X-Public-User yes 71 | http-request del-header X-Bad-Header 72 | ``` 73 | 74 | ## Resources 75 | 76 | * [haproxy_acl](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_acl.md) 77 | * [haproxy_backend](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_backend.md) 78 | * [haproxy_cache](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_cache.md) 79 | * [haproxy_config_defaults](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_config_defaults.md) 80 | * [haproxy_config_global](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_config_global.md) 81 | * [haproxy_fastcgi](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_fastcgi.md) 82 | * [haproxy_frontend](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_frontend.md) 83 | * [haproxy_install](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_install.md) 84 | * [haproxy_listen](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_listen.md) 85 | * [haproxy_mailer](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_mailer.md) 86 | * [haproxy_peer](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_peer.md) 87 | * [haproxy_resolver](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_resolver.md) 88 | * [haproxy_service](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_service.md) 89 | * [haproxy_use_backend](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_use_backend.md) 90 | * [haproxy_userlist](https://github.com/sous-chefs/haproxy/tree/master/documentation/haproxy_userlist.md) 91 | 92 | ## Configuration Validation 93 | 94 | The `haproxy.cfg` file has a few specific rule orderings that will generate validation errors if not loaded properly. If using any combination of the below rules, avoid the errors by loading the rules via `extra_options` to specify the top down order as noted below in config file. 95 | 96 | ### frontend & listen 97 | 98 | ```haproxy 99 | tcp-request connection 100 | tcp-request session 101 | tcp-request content 102 | monitor fail 103 | http-request 104 | reqxxx (any req excluding reqadd, e.g. reqdeny, reqallow) 105 | reqadd 106 | redirect 107 | use_backend 108 | ``` 109 | 110 | ```ruby 111 | extra_options( 112 | 'tcp-request' => 'connection set-src src,ipmask(24)', 113 | 'reqdeny' => '^Host:\ .*\.local', 114 | 'reqallow' => '^Host:\ www\.', 115 | 'use_backend' => 'dynamic' 116 | ) 117 | ``` 118 | 119 | ### backend 120 | 121 | ```haproxy 122 | http-request 123 | reqxxx (any req excluding reqadd, e.g. reqdeny, reqallow) 124 | reqadd 125 | redirect 126 | ``` 127 | 128 | ```ruby 129 | extra_options( 130 | 'http-request' => 'set-path /%[hdr(host)]%[path]', 131 | 'reqdeny' => '^Host:\ .*\.local', 132 | 'reqallow' => '^Host:\ www\.', 133 | 'redirect' => 'dynamic' 134 | ) 135 | ``` 136 | 137 | ## Contributors 138 | 139 | This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false) 140 | 141 | ### Backers 142 | 143 | Thank you to all our backers! 144 | 145 | ![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40) 146 | 147 | ### Sponsors 148 | 149 | Support this project by becoming a sponsor. Your logo will show up here with a link to your website. 150 | 151 | ![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100) 152 | ![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100) 153 | ![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100) 154 | ![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100) 155 | ![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100) 156 | ![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100) 157 | ![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100) 158 | ![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100) 159 | ![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100) 160 | ![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100) 161 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Please refer to [the community cookbook documentation on testing](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/main/TESTING.MD). 4 | -------------------------------------------------------------------------------- /chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # to a Chef Infra Server or Supermarket. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | ehthumbs.db 9 | Icon? 10 | nohup.out 11 | Thumbs.db 12 | .envrc 13 | 14 | # EDITORS # 15 | ########### 16 | .#* 17 | .project 18 | .settings 19 | *_flymake 20 | *_flymake.* 21 | *.bak 22 | *.sw[a-z] 23 | *.tmproj 24 | *~ 25 | \#* 26 | REVISION 27 | TAGS* 28 | tmtags 29 | .vscode 30 | .editorconfig 31 | 32 | ## COMPILED ## 33 | ############## 34 | *.class 35 | *.com 36 | *.dll 37 | *.exe 38 | *.o 39 | *.pyc 40 | *.so 41 | */rdoc/ 42 | a.out 43 | mkmf.log 44 | 45 | # Testing # 46 | ########### 47 | .circleci/* 48 | .codeclimate.yml 49 | .delivery/* 50 | .foodcritic 51 | .kitchen* 52 | .mdlrc 53 | .overcommit.yml 54 | .rspec 55 | .rubocop.yml 56 | .travis.yml 57 | .watchr 58 | .yamllint 59 | azure-pipelines.yml 60 | Dangerfile 61 | examples/* 62 | features/* 63 | Guardfile 64 | kitchen*.yml 65 | mlc_config.json 66 | Procfile 67 | Rakefile 68 | spec/* 69 | test/* 70 | 71 | # SCM # 72 | ####### 73 | .git 74 | .gitattributes 75 | .gitconfig 76 | .github/* 77 | .gitignore 78 | .gitkeep 79 | .gitmodules 80 | .svn 81 | */.bzr/* 82 | */.git 83 | */.hg/* 84 | */.svn/* 85 | 86 | # Berkshelf # 87 | ############# 88 | Berksfile 89 | Berksfile.lock 90 | cookbooks/* 91 | tmp 92 | 93 | # Bundler # 94 | ########### 95 | vendor/* 96 | Gemfile 97 | Gemfile.lock 98 | 99 | # Policyfile # 100 | ############## 101 | Policyfile.rb 102 | Policyfile.lock.json 103 | 104 | # Documentation # 105 | ############# 106 | CODE_OF_CONDUCT* 107 | CONTRIBUTING* 108 | documentation/* 109 | TESTING* 110 | UPGRADING* 111 | 112 | # Vagrant # 113 | ########### 114 | .vagrant 115 | Vagrantfile 116 | -------------------------------------------------------------------------------- /documentation/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sous-chefs/haproxy/8d6fcd56bba2e3d105f7225deb7f1e47e49486b8/documentation/.gitkeep -------------------------------------------------------------------------------- /documentation/haproxy_acl.md: -------------------------------------------------------------------------------- 1 | # haproxy_acl 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Access Control Lists creates a new ACL `` or completes an existing one with new tests. 6 | 7 | The actions generally consist in blocking a request, selecting a backend, or adding a header. 8 | 9 | Introduced: v4.2.0 10 | 11 | ## Actions 12 | 13 | * `:create` 14 | * `:delete` 15 | 16 | ## Properties 17 | 18 | | Name | Type | Default | Description | Allowed Values | 19 | | -------------- | ------------- | ------- | ------------------------------------------------------------ | ------------------------------- | 20 | | `acl` | String, Array | None | The access control list items | Allowed HAProxy acl values | 21 | | `section` | String | None | The section where the acl(s) should be applied | `frontend`, `listen`, `backend` | 22 | | `section_name` | String | None | The name of the specific frontend, listen or backend section | | 23 | 24 | ## Examples 25 | 26 | ```ruby 27 | haproxy_acl 'gina_host hdr(host) -i foo.bar.com' do 28 | section 'frontend' 29 | section_name 'http' 30 | end 31 | ``` 32 | 33 | ```ruby 34 | haproxy_acl 'acls for frontend:http' do 35 | section 'frontend' 36 | section_name 'http' 37 | acl [ 38 | 'rrhost_host hdr(host) -i dave.foo.bar.com foo.foo.com', 39 | 'tile_host hdr(host) -i dough.foo.bar.com', 40 | ] 41 | end 42 | ``` 43 | 44 | ```ruby 45 | haproxy_acl 'acls for listen' do 46 | section 'listen' 47 | section_name 'admin' 48 | acl ['network_allowed src 127.0.0.1'] 49 | end 50 | ``` 51 | -------------------------------------------------------------------------------- /documentation/haproxy_backend.md: -------------------------------------------------------------------------------- 1 | # haproxy_backend 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Backend describes a set of servers to which the proxy will connect to forward incoming connections. 6 | 7 | Introduced: v4.0.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 20 | 21 | | Name | Type | Default | Description | Allowed Values | 22 | | --------------- | ------------- | ------- | ----------------------------------------------------- | -------------------------- | 23 | | `mode` | String | None | Set the running mode or protocol of the instance | `http`, `tcp` | 24 | | `server` | String, Array | None | Servers the backend routes to | | 25 | | `tcp_request` | String, Array | None | HAProxy `tcp-request` settings | | 26 | | `acl` | Array | None | Access control list items | Allowed HAProxy acl values | 27 | | `option` | Array | None | Array of HAProxy `option` directives | | 28 | | `extra_options` | Hash | None | Used for setting any HAProxy directives | | 29 | | `hash_type` | String | None | Specify a method to use for mapping hashes to servers | `consistent`, `map-based` | 30 | 31 | ## Examples 32 | 33 | ```ruby 34 | haproxy_backend 'servers' do 35 | server ['server1 127.0.0.1:8000 maxconn 32'] 36 | end 37 | ``` 38 | 39 | ```ruby 40 | haproxy_backend 'tiles_public' do 41 | server ['tile0 10.0.0.10:80 check weight 1 maxconn 100', 42 | 'tile1 10.0.0.10:80 check weight 1 maxconn 100'] 43 | tcp_request ['content track-sc2 src', 44 | 'content reject if conn_rate_abuse mark_as_abuser'] 45 | option %w(httplog dontlognull forwardfor) 46 | acl ['conn_rate_abuse sc2_conn_rate gt 3000', 47 | 'data_rate_abuse sc2_bytes_out_rate gt 20000000', 48 | 'mark_as_abuser sc1_inc_gpc0 gt 0', 49 | ] 50 | extra_options( 51 | 'stick-table' => 'type ip size 200k expire 2m store conn_rate(60s),bytes_out_rate(60s)', 52 | 'http-request' => 'set-header X-Public-User yes' 53 | ) 54 | end 55 | ``` 56 | -------------------------------------------------------------------------------- /documentation/haproxy_cache.md: -------------------------------------------------------------------------------- 1 | # haproxy_cache 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Cache describes a shared cache for small objects such as CSS, JS and icon files. Useful for web application acceleration. Available in HAProxy version 1.8 and later, and `max_object_size` in 1.9 and later. 6 | 7 | Introduced: v6.3.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | 20 | | Name | Type | Default | Description | Allowed Values | 21 | | ----------------- | ------- | ------------- | --------------------------------------------------- | -------------- | 22 | | `cache_name` | String | name_property | Name of the cache | | 23 | | `total_max_size` | Integer | None | Define the size in RAM of the cache in megabytes | | 24 | | `max_object_size` | Integer | None | Define the maximum size of the objects to be cached | | 25 | | `max_age` | Integer | None | Define the maximum expiration duration in seconds | | 26 | 27 | ## Examples 28 | 29 | ```ruby 30 | haproxy_cache 'test' do 31 | total_max_size 4 32 | max_age 60 33 | max_object_size 1000000 34 | end 35 | ``` 36 | -------------------------------------------------------------------------------- /documentation/haproxy_config_defaults.md: -------------------------------------------------------------------------------- 1 | # haproxy_config_defaults 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Defaults sets default parameters for all other sections following its declaration. Those default parameters are reset by the next "defaults" section. 6 | 7 | Introduced: v4.0.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | 13 | ## Properties 14 | 15 | This resource also uses the following partial resources: 16 | 17 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 18 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 19 | 20 | | Name | Type | Default | Description | Allowed Values | 21 | | ----------------- | ----------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | 22 | | `timeout` | Hash | `{ client: '10s', server: '10s', connect: '10s' }` | Default HAProxy timeout values | | 23 | | `log` | String | `global` | Enable per-instance logging of events and traffic | | 24 | | `mode` | String | `http` | Set the running mode or protocol of the instance | `http`, `tcp` | 25 | | `balance` | String | `roundrobin` | Define the load balancing algorithm to be used in a backend | `roundrobin static-rr`, `leastconn`, `first`, `source`, `uri`, `url_param`, `header`, `rdp-cookie` | 26 | | `stats` | Hash | `{}` | Enable HAProxy statistics | | 27 | | `maxconn` | Integer | None | Sets the maximum per-process number of concurrent connections | | 28 | | `haproxy_retries` | Integer | None | Set the number of retries to perform on a server after a connection failure | | 29 | | `option` | Array | `['httplog', 'dontlognull', 'redispatch', 'tcplog']` | Array of HAProxy `option` directives | | 30 | | `extra_options` | Hash | None | Used for setting any HAProxy directives | | 31 | | `hash_type` | String, nil | None | Specify a method to use for mapping hashes to servers | `consistent`, `map-based`, `nil` | 32 | 33 | ## Examples 34 | 35 | ```ruby 36 | haproxy_config_defaults 'defaults' do 37 | mode 'http' 38 | timeout connect: '5000ms', 39 | client: '5000ms', 40 | server: '5000ms' 41 | haproxy_retries 5 42 | end 43 | ``` 44 | 45 | ```ruby 46 | haproxy_config_defaults 'defaults' do 47 | mode 'http' 48 | timeout connect: '5s', 49 | client: '50s', 50 | server: '50s' 51 | log 'global' 52 | retries 3 53 | end 54 | ``` 55 | -------------------------------------------------------------------------------- /documentation/haproxy_config_global.md: -------------------------------------------------------------------------------- 1 | # haproxy_config_global 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Parameters in the "global" section are process-wide and often OS-specific. 6 | 7 | They are generally set once for all and do not need being changed once correct. 8 | 9 | Introduced: v4.0.0 10 | 11 | ## Actions 12 | 13 | * `:create` 14 | 15 | ## Properties 16 | 17 | This resource also uses the following partial resources: 18 | 19 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 20 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 21 | 22 | | Name | Type | Default | Description | Allowed Values | 23 | | --------------- | --------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ---------------- | 24 | | `pidfile` | String | `/var/run/haproxy.pid` | Writes PIDs of all daemons into file `` | | 25 | | `log` | String, Array | `/dev/log syslog info` | Adds a global syslog server | | 26 | | `daemon` | TrueClass, FalseClass | `true` | Makes the process fork into background | | 27 | | `debug_option` | String | `quiet` | Sets the debugging mode | `quiet`, `debug` | 28 | | `stats` | Hash | `{socket: "/var/run/haproxy.sock user #{haproxy_user} group #{haproxy_group}",timeout: '2m'}` | Enable stats with various options | | 29 | | `maxconn` | Integer | `4096` | Sets the maximum per-process number of concurrent connections | | 30 | | `chroot` | String | None | Changes current directory to `` and performs a chroot() there before dropping privileges | | 31 | | `log_tag` | String | `haproxy` | Specifies the log tag to use for all outgoing logs | | 32 | | `tuning` | Hash | None | A hash of `tune.` | | 33 | | `extra_options` | Hash | None | Used for setting any HAProxy directives | | 34 | 35 | ## Examples 36 | 37 | ```ruby 38 | haproxy_config_global '' do 39 | chroot '/var/lib/haproxy' 40 | daemon true 41 | maxconn 256 42 | log '/dev/log local0' 43 | log_tag 'WARDEN' 44 | pidfile '/var/run/haproxy.pid' 45 | stats socket: '/var/lib/haproxy/stats level admin' 46 | tuning 'bufsize' => '262144' 47 | end 48 | ``` 49 | 50 | ```ruby 51 | haproxy_config_global 'global' do 52 | daemon false 53 | maxconn 4097 54 | chroot '/var/lib/haproxy' 55 | stats socket: '/var/lib/haproxy/haproxy.stat mode 600 level admin', 56 | timeout: '2m' 57 | end 58 | ``` 59 | -------------------------------------------------------------------------------- /documentation/haproxy_fastcgi.md: -------------------------------------------------------------------------------- 1 | # haproxy_fastcgi 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Fastcgi describes a FastCGI applications resource for haproxy to send HTTP requests to Responder FastCGI applications 6 | 7 | Resource available when using HAProxy version >= 2.1. 8 | 9 | Introduced: v8.2.0 10 | 11 | ## Actions 12 | 13 | * `:create` 14 | * `:delete` 15 | 16 | ## Properties 17 | 18 | This resource also uses the following partial resources: 19 | 20 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 21 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 22 | 23 | | Name | Type | Default | Description | Allowed Values | 24 | | ------------ | ------ | ------- | -------------------------------------------------------------------------------- | -------------- | 25 | | `fastcgi` | String | None | Name property - sets the fcgi-app name | | 26 | | `docroot` | String | None | Define the document root on the remote host | | 27 | | `index` | String | None | Define the script name that will be appended after an URI that ends with a slash | | 28 | | `log_stderr` | String | None | Enable logging of STDERR messages reported by the FastCGI application | | 29 | | `option` | Array | None | Array of HAProxy `option` directives | | 30 | 31 | ## Examples 32 | 33 | ```ruby 34 | haproxy_fastcgi 'php-fpm' do 35 | log_stderr 'global' 36 | docroot '/var/www/my-app' 37 | index 'index.php' 38 | option ['keep-conn'] 39 | extra_options('path-info' => '^(/.+\.php)(/.*)?$') 40 | end 41 | ``` 42 | 43 | Generates 44 | 45 | ```ruby 46 | fcgi-app php-fpm 47 | docroot /var/www/my-app 48 | index index.php 49 | log-stderr global 50 | option keep-conn 51 | path-info ^(/.+\.php)(/.*)?$ 52 | ``` 53 | -------------------------------------------------------------------------------- /documentation/haproxy_frontend.md: -------------------------------------------------------------------------------- 1 | # haproxy_frontend 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Frontend describes a set of listening sockets accepting client connections. 6 | 7 | Introduced: v4.0.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 20 | 21 | | Name | Type | Default | Description | Allowed Values | 22 | | ----------------- | ------------ | ------------ | ------------------------------------------------------------------------ | -------------------------- | 23 | | `bind` | String, Hash | `0.0.0.0:80` | String - sets as given. Hash joins with a space | | 24 | | `mode` | String | None | Set the running mode or protocol of the instance | `http`, `tcp` | 25 | | `maxconn` | Integer | None | Sets the maximum per-process number of concurrent connections | | 26 | | `default_backend` | String | None | Specify the backend to use when no "use_backend" rule has been matched | | 27 | | `use_backend` | Array | None | Switch to a specific backend if/unless an ACL-based condition is matched | | 28 | | `acl` | Array | None | Access control list items | Allowed HAProxy acl values | 29 | | `option` | Array | None | Array of HAProxy `option` directives | | 30 | | `stats` | Hash | None | Enable stats with various options | | 31 | 32 | ## Examples 33 | 34 | ```ruby 35 | haproxy_frontend 'http-in' do 36 | bind '*:80' 37 | default_backend 'servers' 38 | end 39 | 40 | haproxy_frontend 'tcp-in' do 41 | mode 'tcp' 42 | bind '*:3307' 43 | default_backend 'tcp-servers' 44 | end 45 | ``` 46 | -------------------------------------------------------------------------------- /documentation/haproxy_install.md: -------------------------------------------------------------------------------- 1 | # haproxy_install 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Install HAProxy from package or source. 6 | 7 | Introduced: v4.0.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | 20 | | Name | Type | Default | Description | Allowed Values | 21 | | -------------------- | ------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------- | 22 | | `install_type` | String | None | Set the installation type | `package`, `source` | 23 | | `bin_prefix` | String | `/usr` | Set the source compile prefix | | 24 | | `sensitive` | Boolean | `true` | Ensure that sensitive resource data is not logged by the chef-client | | 25 | | `use_systemd` | Boolean | `true` | Evalues whether to use systemd based on the nodes init package | | 26 | | `user` | String | `haproxy` | Similar to "uid" but uses the UID of user name `` from /etc/passwd | | 27 | | `group` | String | `haproxy` | Similar to "gid" but uses the GID of group name `` from /etc/group | | 28 | | `package_name` | String | `haproxy` | | | 29 | | `package_version` | String | | | | 30 | | `enable_ius_repo` | Boolean | `false` | Enables the IUS package repo for Centos to install versions >1.5 | | 31 | | `enable_epel_repo` | Boolean | `true` | Enables the epel repo for RHEL based operating systems | | 32 | | `source_version` | String | `2.2.4` | | | 33 | | `source_url` | String | `http://www.haproxy.org/download/2.2.4/src/haproxy-2.2.4.tar.gz` | | | 34 | | `source_checksum` | String | | | | 35 | | `source_target_cpu` | String | `node['kernel']['machine']` | | | 36 | | `source_target_arch` | String | | | | 37 | | `source_target_os` | String | See resource | | | 38 | | `use_libcrypt` | Boolean | `true` | | `true`, `false` | 39 | | `use_pcre` | Boolean | `true` | | `true`, `false` | 40 | | `use_openssl` | Boolean | `true` | Include openssl support () | `true`, `false` | 41 | | `use_zlib` | Boolean | `true` | Include ZLIB support | `true`, `false` | 42 | | `use_linux_tproxy` | Boolean | `true` | | `true`, `false` | 43 | | `use_linux_splice` | Boolean | `true` | | `true`, `false` | 44 | | `use_promex` | Boolean | `false` | Enable the included Prometheus exporter (HAProxy v2.4+) | `true`, `false` | 45 | | `use_systemd` | Boolean | `true` | | `true`, `false` | 46 | | `use_lua` | Boolean | `false` | Include Lua support | `true`, `false` | 47 | | `lua_lib` | String | | Path for lua library files ex: `/opt/lib-5.3.5/lib` | | 48 | | `lua_inc` | String | | Path for lua library files ex: `/opt/lib-5.3.5/include` | | 49 | | `ssl_lib` | String | | Path for openssl library files ex: `/usr/local/openssl/lib` | | 50 | | `ssl_inc` | String | | Path for openssl includes files ex: `/usr/local/openssl/inc` | | 51 | 52 | ## Examples 53 | 54 | ```ruby 55 | haproxy_install 'package' 56 | ``` 57 | 58 | ```ruby 59 | haproxy_install 'source' do 60 | source_url node['haproxy']['source_url'] 61 | source_checksum node['haproxy']['source_checksum'] 62 | source_version node['haproxy']['source_version'] 63 | use_pcre true 64 | use_openssl true 65 | use_zlib true 66 | use_linux_tproxy true 67 | use_linux_splice true 68 | end 69 | ``` 70 | -------------------------------------------------------------------------------- /documentation/haproxy_listen.md: -------------------------------------------------------------------------------- 1 | # haproxy_listen 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Listen defines a complete proxy with its frontend and backend parts combined in one section. 6 | 7 | It is generally useful for TCP-only traffic. 8 | 9 | Introduced: v4.0.0 10 | 11 | ## Actions 12 | 13 | * `:create` 14 | * `:delete` 15 | 16 | ## Properties 17 | 18 | This resource also uses the following partial resources: 19 | 20 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 21 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 22 | 23 | | Name | Type | Default | Description | Allowed Values | 24 | | ----------------- | ------------ | ------------ | ------------------------------------------------------------------------ | -------------------------- | 25 | | `bind` | String, Hash | `0.0.0.0:80` | String - sets as given. Hash - joins with a space | | 26 | | `mode` | String | None | Set the running mode or protocol of the instance | `http`, `tcp` | 27 | | `maxconn` | Integer | None | Sets the maximum per-process number of concurrent connections | | 28 | | `default_backend` | String | None | Specify the backend to use when no "use_backend" rule has been matched | | 29 | | `use_backend` | Array | None | Switch to a specific backend if/unless an ACL-based condition is matched | | 30 | | `http_request` | Array | None | Switch to a specific backend if/unless an ACL-based condition is matched | | 31 | | `http_response` | Array | None | Switch to a specific backend if/unless an ACL-based condition is matched | | 32 | | `acl` | Array | None | Access control list items | Allowed HAProxy acl values | 33 | | `server` | Array | None | Servers the listen section routes to | | 34 | | `stats` | Hash | None | Enable stats with various options | | 35 | | `hash_type` | String | None | Specify a method to use for mapping hashes to servers | `consistent`, `map-based` | 36 | | `option` | Array | None | Array of HAProxy `option` directives | | 37 | 38 | ## Examples 39 | 40 | ```ruby 41 | haproxy_listen 'admin' do 42 | bind '0.0.0.0:1337' 43 | mode 'http' 44 | stats uri: '/', 45 | realm: 'Haproxy-Statistics', 46 | auth: 'user:pwd' 47 | http_request 'add-header X-Proto http' 48 | http_response 'set-header Expires %[date(3600),http_date]' 49 | default_backend 'servers' 50 | extra_options('bind-process' => 'odd') 51 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100', 52 | 'admin1 10.0.0.10:80 check weight 1 maxconn 100'] 53 | end 54 | ``` 55 | -------------------------------------------------------------------------------- /documentation/haproxy_mailer.md: -------------------------------------------------------------------------------- 1 | # haproxy_mailer 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Mailer describes a mailers resource for sending email alerts on server state changes. 6 | 7 | Introduced: v8.0.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | 20 | | Name | Type | Default | Description | Allowed Values | 21 | | --------- | ------------- | ------- | --------------------------------------------------------------------------------------- | -------------- | 22 | | `mailer` | String, Array | None | Defines a mailer inside a mailers section | | 23 | | `timeout` | String | None | Defines the time available for a mail/connection to be made and send to the mail-server | | 24 | 25 | ## Examples 26 | 27 | ```ruby 28 | haproxy_mailer 'mymailer' do 29 | mailer ['smtp1 192.168.0.1:587', 'smtp2 192.168.0.2:587'] 30 | timeout '20s' 31 | end 32 | 33 | haproxy_backend 'admin' do 34 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100'] 35 | extra_options('email-alert' => [ 'mailers mymailers', 36 | 'from test1@horms.org', 37 | 'to test2@horms.org' ]) 38 | end 39 | ``` 40 | -------------------------------------------------------------------------------- /documentation/haproxy_peer.md: -------------------------------------------------------------------------------- 1 | # haproxy_peer 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Peer describes a peers resource for haproxy to propagate entries of any data-types in stick-tables between several haproxy instances over TCP connections in a multi-master fashion. 6 | 7 | Most of the properties are available only when using HAProxy version >= 2.0. To set properties for versions < 2.0, use the `extra_options` hash. See examples below. 8 | 9 | Introduced: v8.0.0 10 | 11 | ## Actions 12 | 13 | * `:create` 14 | * `:delete` 15 | 16 | ## Properties 17 | 18 | This resource also uses the following partial resources: 19 | 20 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 21 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 22 | 23 | | Name | Type | Default | Description | Allowed Values | 24 | | ---------------- | ------------ | ------- | ----------------------------------------------------------------------- | -------------------------- | 25 | | `bind` | String, Hash | None | String - sets as given. Hash joins with a space. HAProxy version >= 2.0 | | 26 | | `state` | String, nil | nil | Set the state of the peers | `enabled`, `disabled`, nil | 27 | | `server` | Array | None | Servers in the peer | | 28 | | `default_bind` | String | None | Defines the binding parameters for the local peer, excepted its address | | 29 | | `default_server` | String | None | Change default options for a server | | 30 | | `table` | Array | None | Configure a stickiness table | | 31 | 32 | ## Examples 33 | 34 | HAProxy version >= 2.0 35 | 36 | ```ruby 37 | haproxy_peer 'mypeers' do 38 | bind '0.0.0.0:1336' 39 | default_server 'ssl verify None' 40 | server ['hostA 127.0.0.10:10000'] 41 | end 42 | ``` 43 | 44 | ```ruby 45 | haproxy_peer 'mypeers' do 46 | bind('0.0.0.0:1336' => 'ssl crt mycerts/pem') 47 | default_server 'ssl verify None' 48 | server ['hostA 127.0.0.10:10000', 'hostB'] 49 | end 50 | ``` 51 | 52 | HAProxy version < 2.0 53 | 54 | ```ruby 55 | haproxy_peer 'mypeers' do 56 | extra_options( 57 | 'peer' => ['haproxy1 192.168.0.1:1024','haproxy2 192.168.0.2:1024'] 58 | ) 59 | end 60 | ``` 61 | -------------------------------------------------------------------------------- /documentation/haproxy_resolver.md: -------------------------------------------------------------------------------- 1 | # haproxy_resolver 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Configuration related to name resolution in HAProxy. There can be as many as resolver sections as needed. 6 | 7 | Each section can contain many name servers. 8 | 9 | Introduced: v4.5.0 10 | 11 | ## Actions 12 | 13 | * `:create` 14 | * `:delete` 15 | 16 | ## Properties 17 | 18 | This resource also uses the following partial resources: 19 | 20 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 21 | * [_extra_options](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_extra_options.md) 22 | 23 | | Name | Type | Default | Description | Allowed Values | 24 | | ------------ | ----- | ------- | ---------------------- | -------------- | 25 | | `nameserver` | Array | None | DNS server description | | 26 | 27 | ## Examples 28 | 29 | ```ruby 30 | haproxy_resolver 'dns' do 31 | nameserver ['google 8.8.8.8:53'] 32 | extra_options('resolve_retries' => 30, 33 | 'timeout' => 'retry 1s') 34 | notifies :restart, 'haproxy_service[haproxy]', :delayed 35 | end 36 | ``` 37 | -------------------------------------------------------------------------------- /documentation/haproxy_service.md: -------------------------------------------------------------------------------- 1 | # haproxy_service 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Configures HAProxy as a systemd service. 6 | To reload HAProxy service add a subscribes option to the resource block. See example below. To reload the HAProxy service add a subscribes option to the resource block. See example below. 7 | 8 | Introduced: v4.0.0 9 | 10 | ## Actions 11 | 12 | * `:create` 13 | * `:delete` 14 | * `:start` 15 | * `:stop` 16 | * `:restart` 17 | * `:reload` 18 | * `:enable` 19 | 20 | ## Properties 21 | 22 | This resource also uses the following partial resources: 23 | 24 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 25 | 26 | | Name | Type | Default | Description | Allowed Values | 27 | | ------------------------- | ------------ | ------------------------ | ---------------------------------------------------------------- | -------------- | 28 | | `bin_prefix` | String | `/usr` | Bin location of the haproxy binary, defaults to /usr | | 29 | | `service_name` | String | `haproxy` | | | 30 | | `systemd_unit_content` | String, Hash | See the service resource | A string or hash that contains a systemd unit file definition | | 31 | | `config_test` | true, false | `true` | Perform configuration file test before performing service action | | 32 | | `config_test_fail_action` | Symbol | `:raise` | Action to perform upon configuration test failure | | 33 | 34 | ## Examples 35 | 36 | ```ruby 37 | haproxy_service 'haproxy' 38 | ``` 39 | 40 | ```ruby 41 | haproxy_service 'haproxy' do 42 | subscribes :reload, 'template[/etc/haproxy/haproxy.cfg]', :delayed 43 | end 44 | ``` 45 | 46 | ```ruby 47 | haproxy_service 'haproxy' do 48 | subscribes :reload, ['template[/etc/haproxy/haproxy.cfg]', 'file[/etc/haproxy/ssl/haproxy.pem]'], :delayed 49 | end 50 | ``` 51 | -------------------------------------------------------------------------------- /documentation/haproxy_use_backend.md: -------------------------------------------------------------------------------- 1 | # haproxy_use_backend 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Switch to a specific backend if/unless an ACL-based condition is matched. 6 | 7 | Introduced: v4.2.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | 20 | | Name | Type | Default | Description | Allowed Values | 21 | | -------------- | ------------- | ------- | ------------------------------------------------------------------------ | ------------------------------- | 22 | | `use_backend` | String, Array | None | Switch to a specific backend if/unless an ACL-based condition is matched | | 23 | | `section` | String | None | The section where the acl(s) should be applied | `frontend`, `listen`, `backend` | 24 | | `section_name` | String | None | The name of the specific frontend, listen or backend section | | 25 | 26 | ## Examples 27 | 28 | ```ruby 29 | haproxy_use_backend 'gina if gina_host' do 30 | section 'frontend' 31 | section_name 'http' 32 | end 33 | ``` 34 | 35 | ```ruby 36 | haproxy_use_backend 'use_backends for frontend:http' do 37 | section 'frontend' 38 | section_name 'http' 39 | use_backend [ 40 | 'rrhost if rrhost_host', 41 | 'tiles_public if tile_host', 42 | ] 43 | end 44 | ``` 45 | -------------------------------------------------------------------------------- /documentation/haproxy_userlist.md: -------------------------------------------------------------------------------- 1 | # haproxy_userlist 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Control access to frontend/backend/listen sections or to http stats by allowing only authenticated and authorized users. 6 | 7 | Introduced: v4.1.0 8 | 9 | ## Actions 10 | 11 | * `:create` 12 | * `:delete` 13 | 14 | ## Properties 15 | 16 | This resource also uses the following partial resources: 17 | 18 | * [_config_file](https://github.com/sous-chefs/haproxy/tree/master/documentation/partial_config_file.md) 19 | 20 | | Name | Type | Default | Description | Allowed Values | 21 | | ------- | ---- | ------- | ------------------------------------------------ | -------------- | 22 | | `group` | Hash | None | Adds group `` to the current userlist | | 23 | | `user` | Hash | None | Adds user `` to the current userlist | | 24 | 25 | ## Examples 26 | 27 | ```ruby 28 | haproxy_userlist 'mylist' do 29 | group 'G1' => 'users tiger,scott', 30 | 'G2' => 'users xdb,scott' 31 | user 'tiger' => 'password $6$k6y3o.eP$JlKBx9za9667qe4(...)xHSwRv6J.C0/D7cV91', 32 | 'scott' => 'insecure-password elgato', 33 | 'xdb' => 'insecure-password hello' 34 | end 35 | ``` 36 | -------------------------------------------------------------------------------- /documentation/partial_config_file.md: -------------------------------------------------------------------------------- 1 | # Partial Resource - _config_file 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Provides properties to control the generation of the HAProxy config file. 6 | 7 | Introduced: v11.0.0 8 | 9 | ## Properties 10 | 11 | | Name | Type | Default | Description | Allowed Values | 12 | | ------------------ | ------ | -------------------------- | ----------------------------------------------------------- | --------------- | 13 | | `user` | String | `haproxy` | Set to override haproxy user, defaults to haproxy | | 14 | | `group` | String | `haproxy` | Set to override haproxy group, defaults to haproxy | | 15 | | `config_dir` | String | `/etc/haproxy` | The directory where the HAProxy configuration resides | Valid directory | 16 | | `config_dir_mode` | String | `0750` | Set to override haproxy config dir mode, defaults to 0750 | | 17 | | `config_file` | String | `/etc/haproxy/haproxy.cfg` | The HAProxy configuration file | Valid file name | 18 | | `config_file_mode` | String | `0640` | Set to override haproxy config file mode, defaults to 0640 | | 19 | | `cookbook` | String | `haproxy` | Template source cookbook for the haproxy configuration file | | 20 | | `template` | String | `haproxy.cfg.erb` | Template source file for the haproxy configuration file | | 21 | -------------------------------------------------------------------------------- /documentation/partial_extra_options.md: -------------------------------------------------------------------------------- 1 | # Partial Resource - _extra_options 2 | 3 | [Back To Resource List](https://github.com/sous-chefs/haproxy#resources) 4 | 5 | Provides properties to supply arbitrary parameters to the haproxy configuration template. 6 | 7 | Introduced: v11.0.0 8 | 9 | ## Properties 10 | 11 | | Name | Type | Default | Description | Allowed Values | 12 | | --------------- | ---- | ------- | --------------------------------------- | -------------- | 13 | | `extra_options` | Hash | None | Used for setting any HAProxy directives | | 14 | -------------------------------------------------------------------------------- /files/haproxy-default: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sous-chefs/haproxy/8d6fcd56bba2e3d105f7225deb7f1e47e49486b8/files/haproxy-default -------------------------------------------------------------------------------- /kitchen.dokken.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: dokken 3 | privileged: true 4 | chef_version: <%= ENV['CHEF_VERSION'] || 'current' %> 5 | 6 | transport: { name: dokken } 7 | provisioner: { name: dokken } 8 | 9 | platforms: 10 | - name: almalinux-8 11 | driver: 12 | image: dokken/almalinux-8 13 | pid_one_command: /usr/lib/systemd/systemd 14 | 15 | - name: almalinux-9 16 | driver: 17 | image: dokken/almalinux-9 18 | pid_one_command: /usr/lib/systemd/systemd 19 | 20 | - name: almalinux-10 21 | driver: 22 | image: dokken/almalinux-10 23 | pid_one_command: /usr/lib/systemd/systemd 24 | 25 | - name: amazonlinux-2023 26 | driver: 27 | image: dokken/amazonlinux-2023 28 | pid_one_command: /usr/lib/systemd/systemd 29 | 30 | - name: centos-stream-9 31 | driver: 32 | image: dokken/centos-stream-9 33 | pid_one_command: /usr/lib/systemd/systemd 34 | 35 | - name: centos-stream-10 36 | driver: 37 | image: dokken/centos-stream-10 38 | pid_one_command: /usr/lib/systemd/systemd 39 | 40 | - name: debian-11 41 | driver: 42 | image: dokken/debian-11 43 | pid_one_command: /bin/systemd 44 | 45 | - name: debian-12 46 | driver: 47 | image: dokken/debian-12 48 | pid_one_command: /bin/systemd 49 | 50 | - name: fedora-latest 51 | driver: 52 | image: dokken/fedora-latest 53 | pid_one_command: /usr/lib/systemd/systemd 54 | 55 | - name: opensuse-leap-15 56 | driver: 57 | image: dokken/opensuse-leap-15 58 | pid_one_command: /usr/lib/systemd/systemd 59 | 60 | - name: oraclelinux-8 61 | driver: 62 | image: dokken/oraclelinux-8 63 | pid_one_command: /usr/lib/systemd/systemd 64 | 65 | - name: oraclelinux-9 66 | driver: 67 | image: dokken/oraclelinux-9 68 | pid_one_command: /usr/lib/systemd/systemd 69 | 70 | - name: rockylinux-8 71 | driver: 72 | image: dokken/rockylinux-8 73 | pid_one_command: /usr/lib/systemd/systemd 74 | 75 | - name: rockylinux-9 76 | driver: 77 | image: dokken/rockylinux-9 78 | pid_one_command: /usr/lib/systemd/systemd 79 | 80 | - name: ubuntu-20.04 81 | driver: 82 | image: dokken/ubuntu-20.04 83 | pid_one_command: /bin/systemd 84 | 85 | - name: ubuntu-22.04 86 | driver: 87 | image: dokken/ubuntu-22.04 88 | pid_one_command: /bin/systemd 89 | 90 | - name: ubuntu-24.04 91 | driver: 92 | image: dokken/ubuntu-24.04 93 | pid_one_command: /bin/systemd 94 | -------------------------------------------------------------------------------- /kitchen.exec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: { name: exec } 3 | transport: { name: exec } 4 | 5 | platforms: 6 | - name: macos-latest 7 | - name: windows-latest 8 | -------------------------------------------------------------------------------- /kitchen.global.yml: -------------------------------------------------------------------------------- 1 | --- 2 | provisioner: 3 | name: chef_infra 4 | product_name: chef 5 | product_version: <%= ENV['CHEF_VERSION'] || 'latest' %> 6 | channel: stable 7 | install_strategy: once 8 | chef_license: accept 9 | enforce_idempotency: <%= ENV['ENFORCE_IDEMPOTENCY'] || true %> 10 | multiple_converge: <%= ENV['MULTIPLE_CONVERGE'] || 2 %> 11 | deprecations_as_errors: true 12 | log_level: <%= ENV['CHEF_LOG_LEVEL'] || 'auto' %> 13 | 14 | verifier: 15 | name: inspec 16 | 17 | platforms: 18 | - name: almalinux-8 19 | - name: almalinux-9 20 | - name: amazonlinux-2023 21 | - name: centos-stream-9 22 | - name: debian-11 23 | - name: debian-12 24 | - name: fedora-latest 25 | - name: opensuse-leap-15 26 | - name: oraclelinux-8 27 | - name: oraclelinux-9 28 | - name: rockylinux-8 29 | - name: rockylinux-9 30 | - name: ubuntu-20.04 31 | - name: ubuntu-22.04 32 | - name: ubuntu-24.04 33 | -------------------------------------------------------------------------------- /kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | provisioner: 6 | name: chef_zero 7 | deprecations_as_errors: true 8 | chef_license: accept 9 | product_name: chef 10 | product_version: <%= ENV['CHEF_VERSION'] || 'latest' %> 11 | install_strategy: always 12 | log_level: <%= ENV['CHEF_LOG_LEVEL'] || 'auto' %> 13 | 14 | verifier: 15 | name: inspec 16 | 17 | platforms: 18 | - name: amazonlinux-2023 19 | - name: centos-stream-8 20 | - name: centos-stream-9 21 | - name: debian-11 22 | - name: debian-12 23 | - name: ubuntu-20.04 24 | - name: ubuntu-22.04 25 | - name: fedora-latest 26 | 27 | suites: 28 | - name: package 29 | run_list: 30 | - recipe[test::package] 31 | - name: source-2.4 32 | run_list: 33 | - recipe[test::source_24] 34 | - name: source_2.6 35 | run_list: 36 | - recipe[test::source_26] 37 | - name: source_2.8 38 | run_list: 39 | - recipe[test::source_28] 40 | - name: source_2.9 41 | run_list: 42 | - recipe[test::source_29] 43 | - name: source_default 44 | run_list: 45 | - recipe[test::source] 46 | - name: source_lua 47 | run_list: 48 | - recipe[test::source_lua] 49 | - name: source_openssl 50 | run_list: 51 | - recipe[test::source_openssl] 52 | - name: config_2 53 | run_list: 54 | - recipe[test::config_2] 55 | - name: config_3 56 | run_list: 57 | - recipe[test::config_3] 58 | - name: config_4 59 | run_list: 60 | - recipe[test::config_4] 61 | - name: config_backend_search 62 | run_list: 63 | - recipe[test::config_backend_search] 64 | - name: config_acl 65 | run_list: 66 | - recipe[test::config_acl] 67 | - name: config_resolver 68 | run_list: 69 | - recipe[test::config_resolver] 70 | - name: config_ssl_redirect 71 | run_list: 72 | - recipe[test::config_ssl_redirect] 73 | - name: config_custom_template 74 | run_list: 75 | - recipe[test::config_custom_template] 76 | - name: config_array 77 | run_list: 78 | - recipe[test::config_array] 79 | - name: config_fastcgi 80 | run_list: 81 | - recipe[test::config_fastcgi] 82 | -------------------------------------------------------------------------------- /libraries/helpers.rb: -------------------------------------------------------------------------------- 1 | module Haproxy 2 | module Cookbook 3 | module Helpers 4 | def haproxy_version 5 | v = Mixlib::ShellOut.new("haproxy -v | grep version | awk '{ print $3 }'") 6 | v.run_command.stdout.to_f 7 | end 8 | 9 | def source_package_list 10 | case node['platform_family'] 11 | when 'debian' 12 | %w(libpcre3-dev libssl-dev zlib1g-dev libsystemd-dev) 13 | when 'rhel', 'amazon', 'fedora' 14 | %w(pcre-devel openssl-devel zlib-devel systemd-devel tar) 15 | when 'suse' 16 | %w(pcre-devel libopenssl-devel zlib-devel systemd-devel) 17 | end 18 | end 19 | 20 | def ius_package 21 | { 22 | name: 'ius-release.rpm', 23 | url: 'https://repo.ius.io/ius-release-el7.rpm', 24 | } 25 | end 26 | 27 | def ius_platform_valid? 28 | platform_family?('rhel') && (platform_version.to_i == 6 || platform_version.to_i == 7) 29 | end 30 | 31 | def target_os(source_version) 32 | major_revision = node['kernel']['release'].split('.')[0..1].join('.').to_f 33 | minor_revision = node['kernel']['release'].split('.')[2].split('-').first.to_i 34 | 35 | if major_revision > 2.6 36 | source_version.chars.first == '1' ? 'linux2628' : 'linux-glibc' 37 | elsif major_revision == 2.6 38 | if minor_revision >= 28 39 | source_version.chars.first == '1' ? 'linux2628' : 'linux-glibc' 40 | else 41 | 'linux26' 42 | end 43 | else 44 | 'generic' 45 | end 46 | end 47 | 48 | def systemd_command(bin_prefix) 49 | if haproxy_version < 1.8 50 | ::File.join(bin_prefix, 'sbin', 'haproxy-systemd-wrapper') 51 | else 52 | ::File.join(bin_prefix, 'sbin', 'haproxy') + ' -Ws' 53 | end 54 | end 55 | 56 | def default_systemd_unit_content 57 | { 58 | 'Unit' => { 59 | 'Description' => 'HAProxy Load Balancer', 60 | 'Documentation' => 'file:/usr/share/doc/haproxy/configuration.txt.gz', 61 | 'After' => %w(network.target syslog.service), 62 | }, 63 | 'Service' => { 64 | 'EnvironmentFile' => '-/etc/default/haproxy', 65 | 'Environment' => "CONFIG=#{config_file} PIDFILE=/run/haproxy.pid", 66 | 'ExecStartPre' => "#{bin_prefix}/sbin/haproxy -f $CONFIG -c -q", 67 | 'ExecStart' => "#{systemd_command(bin_prefix)} -f $CONFIG -p $PIDFILE $OPTIONS", 68 | 'ExecReload' => [ 69 | "#{bin_prefix}/sbin/haproxy -f $CONFIG -c -q", 70 | '/bin/kill -USR2 $MAINPID', 71 | ], 72 | 'KillSignal' => 'TERM', 73 | 'User' => 'root', 74 | 'WorkingDirectory' => '/', 75 | 'KillMode' => 'mixed', 76 | 'Restart' => 'always', 77 | }, 78 | 'Install' => { 79 | 'WantedBy' => 'multi-user.target', 80 | }, 81 | } 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /libraries/resource.rb: -------------------------------------------------------------------------------- 1 | module Haproxy 2 | module Cookbook 3 | module ResourceHelpers 4 | def haproxy_config_resource_init 5 | haproxy_config_resource_create unless haproxy_config_resource_exist? 6 | end 7 | 8 | def haproxy_config_resource 9 | return unless haproxy_config_resource_exist? 10 | 11 | find_resource!(:template, new_resource.config_file) 12 | end 13 | 14 | private 15 | 16 | def haproxy_config_resource_exist? 17 | !find_resource!(:template, new_resource.config_file).nil? 18 | rescue Chef::Exceptions::ResourceNotFound 19 | false 20 | end 21 | 22 | def haproxy_config_resource_create 23 | with_run_context(:root) do 24 | declare_resource(:directory, ::File.dirname(new_resource.config_file)) do 25 | owner new_resource.user 26 | group new_resource.group 27 | mode new_resource.config_dir_mode 28 | 29 | recursive true 30 | 31 | action :create 32 | end 33 | 34 | declare_resource(:template, new_resource.config_file) do 35 | cookbook new_resource.cookbook 36 | source new_resource.template 37 | 38 | owner new_resource.user 39 | group new_resource.group 40 | mode new_resource.config_file_mode 41 | sensitive new_resource.sensitive 42 | 43 | helpers(Haproxy::Cookbook::TemplateHelpers) 44 | 45 | action :nothing 46 | delayed_action :create 47 | end 48 | end 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /libraries/template.rb: -------------------------------------------------------------------------------- 1 | module Haproxy 2 | module Cookbook 3 | module TemplateHelpers 4 | def nil_or_empty?(v) 5 | v.nil? || (v.respond_to?(:empty?) && v.empty?) 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'haproxy' 2 | maintainer 'Sous Chefs' 3 | maintainer_email 'help@sous-chefs.org' 4 | license 'Apache-2.0' 5 | description 'Installs and configures haproxy' 6 | version '12.4.0' 7 | source_url 'https://github.com/sous-chefs/haproxy' 8 | issues_url 'https://github.com/sous-chefs/haproxy/issues' 9 | chef_version '>= 16' 10 | 11 | supports 'debian' 12 | supports 'ubuntu' 13 | supports 'centos' 14 | supports 'amazon' 15 | supports 'opensuseleap' 16 | depends 'yum-epel' 17 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"], 4 | "packageRules": [ 5 | { 6 | "groupName": "Actions", 7 | "matchUpdateTypes": ["minor", "patch", "pin"], 8 | "automerge": true, 9 | "addLabels": ["Release: Patch", "Skip: Announcements"] 10 | }, 11 | { 12 | "groupName": "Actions", 13 | "matchUpdateTypes": ["major"], 14 | "automerge": false, 15 | "addLabels": ["Release: Patch", "Skip: Announcements"] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /resources/acl.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | 3 | property :acl, [String, Array], 4 | name_property: true, 5 | coerce: proc { |p| Array(p) }, 6 | description: 'The access control list items' 7 | 8 | property :section, String, 9 | required: true, 10 | equal_to: %w(frontend listen backend), 11 | description: 'The section where the acl(s) should be applied' 12 | 13 | property :section_name, String, 14 | required: true, 15 | description: 'The name of the specific frontend, listen or backend section' 16 | 17 | unified_mode true 18 | 19 | action_class do 20 | include Haproxy::Cookbook::ResourceHelpers 21 | end 22 | 23 | action :create do 24 | haproxy_config_resource_init 25 | 26 | haproxy_config_resource.variables[new_resource.section] ||= {} 27 | 28 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name] ||= {} 29 | 30 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['acl'] ||= [] 31 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['acl'].push(new_resource.acl) 32 | end 33 | 34 | action :delete do 35 | haproxy_config_resource_init 36 | 37 | haproxy_config_resource.variables[new_resource.section] ||= {} 38 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['acl'] ||= [] 39 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['acl'].delete(new_resource.acl) 40 | end 41 | -------------------------------------------------------------------------------- /resources/backend.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :mode, String, 5 | equal_to: %w(http tcp health), 6 | description: 'Set the running mode or protocol of the instance' 7 | 8 | property :server, [String, Array], 9 | coerce: proc { |p| Array(p) }, 10 | description: 'Servers the backend routes to' 11 | 12 | property :tcp_request, [String, Array], 13 | coerce: proc { |p| Array(p) }, 14 | description: 'HAProxy tcp-request settings' 15 | 16 | property :acl, Array, 17 | description: 'Access control list items' 18 | 19 | property :option, Array, 20 | description: 'Array of HAProxy option directives' 21 | 22 | property :hash_type, String, 23 | equal_to: %w(consistent map-based), 24 | description: 'Specify a method to use for mapping hashes to servers' 25 | 26 | unified_mode true 27 | 28 | action_class do 29 | include Haproxy::Cookbook::ResourceHelpers 30 | end 31 | 32 | action :create do 33 | haproxy_config_resource_init 34 | 35 | haproxy_config_resource.variables['backend'] ||= {} 36 | 37 | haproxy_config_resource.variables['backend'][new_resource.name] ||= {} 38 | haproxy_config_resource.variables['backend'][new_resource.name]['mode'] = new_resource.mode if property_is_set?(:mode) 39 | 40 | if property_is_set?(:server) 41 | haproxy_config_resource.variables['backend'][new_resource.name]['server'] ||= [] 42 | haproxy_config_resource.variables['backend'][new_resource.name]['server'].push(new_resource.server) 43 | end 44 | 45 | if property_is_set?(:tcp_request) 46 | haproxy_config_resource.variables['backend'][new_resource.name]['tcp_request'] ||= [] 47 | haproxy_config_resource.variables['backend'][new_resource.name]['tcp_request'].push(new_resource.tcp_request) 48 | end 49 | 50 | if property_is_set?(:acl) 51 | haproxy_config_resource.variables['backend'][new_resource.name]['acl'] ||= [] 52 | haproxy_config_resource.variables['backend'][new_resource.name]['acl'].push(new_resource.acl) 53 | end 54 | 55 | if property_is_set?(:option) 56 | haproxy_config_resource.variables['backend'][new_resource.name]['option'] ||= [] 57 | haproxy_config_resource.variables['backend'][new_resource.name]['option'].concat(new_resource.option) 58 | end 59 | 60 | haproxy_config_resource.variables['backend'][new_resource.name]['hash_type'] = new_resource.hash_type if property_is_set?(:hash_type) 61 | haproxy_config_resource.variables['backend'][new_resource.name]['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 62 | end 63 | 64 | action :delete do 65 | haproxy_config_resource_init 66 | 67 | haproxy_config_resource.variables['backend'] ||= {} 68 | 69 | haproxy_config_resource.variables['backend'][new_resource.name] ||= {} 70 | haproxy_config_resource.variables['backend'].delete(new_resource.name) if haproxy_config_resource.variables['backend'].key?(new_resource.name) 71 | end 72 | -------------------------------------------------------------------------------- /resources/cache.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | 3 | property :cache_name, String, 4 | name_property: true, 5 | description: 'Name of the cache' 6 | 7 | property :total_max_size, Integer, 8 | description: 'Define the size in RAM of the cache in megabytes' 9 | 10 | property :max_object_size, Integer, 11 | description: 'Define the maximum size of the objects to be cached' 12 | 13 | property :max_age, Integer, 14 | description: 'Define the maximum expiration duration in seconds' 15 | 16 | unified_mode true 17 | 18 | action_class do 19 | include Haproxy::Cookbook::ResourceHelpers 20 | end 21 | 22 | action :create do 23 | haproxy_config_resource_init 24 | 25 | haproxy_config_resource.variables['cache'] ||= {} 26 | 27 | haproxy_config_resource.variables['cache'][new_resource.cache_name] ||= {} 28 | haproxy_config_resource.variables['cache'][new_resource.cache_name]['total_max_size'] = new_resource.total_max_size if property_is_set?(:total_max_size) 29 | haproxy_config_resource.variables['cache'][new_resource.cache_name]['max_object_size'] = new_resource.max_object_size if property_is_set?(:max_object_size) 30 | haproxy_config_resource.variables['cache'][new_resource.cache_name]['max_age'] = new_resource.max_age if property_is_set?(:max_age) 31 | end 32 | 33 | action :delete do 34 | haproxy_config_resource_init 35 | 36 | haproxy_config_resource.variables['cache'] ||= {} 37 | 38 | haproxy_config_resource.variables['cache'][new_resource.cache_name] ||= {} 39 | haproxy_config_resource.variables['cache'].delete(new_resource.cache_name) if haproxy_config_resource.variables['cache'].key?(new_resource.cache_name) 40 | end 41 | -------------------------------------------------------------------------------- /resources/config_defaults.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :timeout, Hash, 5 | default: { client: '10s', server: '10s', connect: '10s' }, 6 | description: 'Default HAProxy timeout values' 7 | 8 | property :log, String, 9 | default: 'global', 10 | description: 'Enable per-instance logging of events and traffic' 11 | 12 | property :mode, String, 13 | default: 'http', 14 | equal_to: %w(http tcp health), 15 | description: 'Set the running mode or protocol of the instance' 16 | 17 | property :balance, String, 18 | default: 'roundrobin', 19 | equal_to: %w(roundrobin static-rr leastconn first source uri url_param header rdp-cookie), 20 | description: 'Define the load balancing algorithm to be used in a backend' 21 | 22 | property :option, Array, 23 | default: %w(httplog dontlognull redispatch tcplog), 24 | description: 'Array of HAProxy option directives' 25 | 26 | property :stats, Hash, 27 | default: {}, 28 | description: 'Enable HAProxy statistics' 29 | 30 | property :maxconn, Integer, 31 | description: 'Sets the maximum per-process number of concurrent connections' 32 | 33 | property :haproxy_retries, Integer, 34 | description: 'Set the number of retries to perform on a server after a connection failure' 35 | 36 | property :hash_type, [String, nil], 37 | equal_to: ['consistent', 'map-based', nil], 38 | description: 'Specify a method to use for mapping hashes to servers' 39 | 40 | unified_mode true 41 | 42 | action_class do 43 | include Haproxy::Cookbook::ResourceHelpers 44 | end 45 | 46 | action :create do 47 | haproxy_config_resource_init 48 | 49 | haproxy_config_resource.variables['defaults'] ||= {} 50 | 51 | haproxy_config_resource.variables['defaults']['timeout'] = new_resource.timeout 52 | haproxy_config_resource.variables['defaults']['log'] = new_resource.log 53 | haproxy_config_resource.variables['defaults']['mode'] = new_resource.mode 54 | haproxy_config_resource.variables['defaults']['balance'] = new_resource.balance 55 | 56 | haproxy_config_resource.variables['defaults']['option'] ||= [] 57 | haproxy_config_resource.variables['defaults']['option'].push(new_resource.option).flatten! 58 | 59 | haproxy_config_resource.variables['defaults']['stats'] = new_resource.stats 60 | haproxy_config_resource.variables['defaults']['maxconn'] = new_resource.maxconn.to_s if property_is_set?(:maxconn) 61 | haproxy_config_resource.variables['defaults']['retries'] = new_resource.haproxy_retries.to_s if property_is_set?(:haproxy_retries) 62 | haproxy_config_resource.variables['defaults']['hash_type'] = new_resource.hash_type if property_is_set?(:hash_type) 63 | haproxy_config_resource.variables['defaults']['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 64 | end 65 | -------------------------------------------------------------------------------- /resources/config_global.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :pidfile, String, 5 | default: '/var/run/haproxy.pid', 6 | description: 'Writes PIDs of all daemons into file ' 7 | 8 | property :log, [String, Array], 9 | default: '/dev/log syslog info', 10 | description: 'Adds a global syslog server' 11 | 12 | property :daemon, [true, false], 13 | default: true, 14 | description: 'Makes the process fork into background' 15 | 16 | property :debug_option, String, 17 | default: 'quiet', 18 | equal_to: %w(quiet debug), 19 | description: 'Sets the debugging mode' 20 | 21 | property :stats, Hash, 22 | default: lazy { 23 | { 24 | socket: "/var/run/haproxy.sock user #{user} group #{group}", 25 | timeout: '2m', 26 | } 27 | }, 28 | description: 'Enable stats with various options' 29 | 30 | property :maxconn, [Integer, String], 31 | default: 4096, 32 | description: 'Sets the maximum per-process number of concurrent connections' 33 | 34 | property :chroot, String, 35 | description: 'Changes current directory to and performs a chroot() there before dropping privileges' 36 | 37 | property :log_tag, String, 38 | default: 'haproxy', 39 | description: 'Specifies the log tag to use for all outgoing logs' 40 | 41 | property :tuning, Hash, 42 | description: 'A hash of tune.' 43 | 44 | unified_mode true 45 | 46 | action_class do 47 | include Haproxy::Cookbook::ResourceHelpers 48 | end 49 | 50 | action :create do 51 | haproxy_config_resource_init 52 | 53 | haproxy_config_resource.variables['global'] ||= {} 54 | 55 | haproxy_config_resource.variables['global']['user'] = new_resource.user 56 | haproxy_config_resource.variables['global']['group'] = new_resource.group 57 | haproxy_config_resource.variables['global']['pidfile'] = new_resource.pidfile 58 | 59 | haproxy_config_resource.variables['global']['log'] ||= [] 60 | haproxy_config_resource.variables['global']['log'].push(new_resource.log) 61 | 62 | haproxy_config_resource.variables['global']['log_tag'] = new_resource.log_tag 63 | haproxy_config_resource.variables['global']['chroot'] = new_resource.chroot if property_is_set?(:chroot) 64 | haproxy_config_resource.variables['global']['daemon'] = new_resource.daemon.to_s 65 | haproxy_config_resource.variables['global']['debug_option'] = new_resource.debug_option 66 | haproxy_config_resource.variables['global']['maxconn'] = new_resource.maxconn 67 | haproxy_config_resource.variables['global']['stats'] = new_resource.stats 68 | haproxy_config_resource.variables['global']['tuning'] = new_resource.tuning if property_is_set?(:tuning) 69 | haproxy_config_resource.variables['global']['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 70 | end 71 | -------------------------------------------------------------------------------- /resources/fastcgi.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | 3 | property :fastcgi, String, 4 | name_property: true, 5 | description: 'Name property - sets the fcgi-app name' 6 | 7 | property :docroot, String, 8 | description: 'Define the document root on the remote host' 9 | 10 | property :index, String, 11 | description: 'Define the script name that will be appended after an URI that ends with a slash' 12 | 13 | property :log_stderr, String, 14 | description: 'Enable logging of STDERR messages reported by the FastCGI application' 15 | 16 | property :option, Array, 17 | description: 'Array of HAProxy option directives' 18 | 19 | property :extra_options, Hash, 20 | description: 'Used for setting any HAProxy directives' 21 | 22 | unified_mode true 23 | 24 | action_class do 25 | include Haproxy::Cookbook::ResourceHelpers 26 | end 27 | 28 | action :create do 29 | haproxy_config_resource_init 30 | 31 | haproxy_config_resource.variables['fastcgi'] ||= {} 32 | 33 | haproxy_config_resource.variables['fastcgi'][new_resource.name] ||= {} 34 | haproxy_config_resource.variables['fastcgi'][new_resource.name]['docroot'] = new_resource.docroot if property_is_set?(:docroot) 35 | haproxy_config_resource.variables['fastcgi'][new_resource.name]['index'] = new_resource.index if property_is_set?(:index) 36 | haproxy_config_resource.variables['fastcgi'][new_resource.name]['log_stderr'] = new_resource.log_stderr if property_is_set?(:log_stderr) 37 | 38 | if property_is_set?(:option) 39 | haproxy_config_resource.variables['fastcgi'][new_resource.name]['option'] ||= [] 40 | haproxy_config_resource.variables['fastcgi'][new_resource.name]['option'].concat(new_resource.option) 41 | end 42 | 43 | haproxy_config_resource.variables['fastcgi'][new_resource.name]['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 44 | end 45 | 46 | action :delete do 47 | haproxy_config_resource_init 48 | 49 | haproxy_config_resource.variables['fastcgi'] ||= {} 50 | 51 | haproxy_config_resource.variables['fastcgi'][new_resource.name] ||= {} 52 | haproxy_config_resource.variables['fastcgi'].delete(new_resource.name) if haproxy_config_resource.variables['fastcgi'].key?(new_resource.name) 53 | end 54 | -------------------------------------------------------------------------------- /resources/frontend.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :bind, [String, Hash], 5 | default: '0.0.0.0:80', 6 | description: 'String - sets as given. Hash - joins with a space' 7 | 8 | property :mode, String, 9 | equal_to: %w(http tcp health), 10 | description: 'Set the running mode or protocol of the instance' 11 | 12 | property :maxconn, [Integer, String], 13 | coerce: proc { |p| p.to_s }, 14 | description: 'Sets the maximum per-process number of concurrent connections' 15 | 16 | property :default_backend, String, 17 | description: 'Specify the backend to use when no "use_backend" rule has been matched' 18 | 19 | property :use_backend, Array, 20 | description: 'Switch to a specific backend if/unless an ACL-based condition is matched' 21 | 22 | property :acl, Array, 23 | description: 'Access control list items' 24 | 25 | property :option, Array, 26 | description: 'Array of HAProxy option directives' 27 | 28 | property :stats, Hash, 29 | description: 'Enable stats with various options' 30 | 31 | unified_mode true 32 | 33 | action_class do 34 | include Haproxy::Cookbook::ResourceHelpers 35 | end 36 | 37 | action :create do 38 | haproxy_config_resource_init 39 | 40 | haproxy_config_resource.variables['frontend'] ||= {} 41 | 42 | haproxy_config_resource.variables['frontend'][new_resource.name] ||= {} 43 | haproxy_config_resource.variables['frontend'][new_resource.name]['bind'] = [] 44 | 45 | if new_resource.bind.is_a?(Hash) 46 | new_resource.bind.map do |addresses, ports| 47 | Array(addresses).product(Array(ports)).each do |combo| 48 | haproxy_config_resource.variables['frontend'][new_resource.name]['bind'].push(combo.join(' ').strip) 49 | end 50 | end 51 | else 52 | haproxy_config_resource.variables['frontend'][new_resource.name]['bind'].push(new_resource.bind) 53 | end 54 | 55 | haproxy_config_resource.variables['frontend'][new_resource.name]['default_backend'] = new_resource.default_backend if property_is_set?(:default_backend) 56 | haproxy_config_resource.variables['frontend'][new_resource.name]['mode'] = new_resource.mode if property_is_set?(:mode) 57 | haproxy_config_resource.variables['frontend'][new_resource.name]['stats'] = new_resource.stats if property_is_set?(:stats) 58 | haproxy_config_resource.variables['frontend'][new_resource.name]['maxconn'] = new_resource.maxconn if property_is_set?(:maxconn) 59 | haproxy_config_resource.variables['frontend'][new_resource.name]['use_backend'] = new_resource.use_backend if property_is_set?(:use_backend) 60 | 61 | if property_is_set?(:acl) 62 | haproxy_config_resource.variables['frontend'][new_resource.name]['acl'] ||= [] 63 | haproxy_config_resource.variables['frontend'][new_resource.name]['acl'].push(new_resource.acl) 64 | end 65 | 66 | if property_is_set?(:option) 67 | haproxy_config_resource.variables['frontend'][new_resource.name]['option'] ||= [] 68 | haproxy_config_resource.variables['frontend'][new_resource.name]['option'].concat(new_resource.option) 69 | end 70 | 71 | haproxy_config_resource.variables['frontend'][new_resource.name]['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 72 | end 73 | 74 | action :delete do 75 | haproxy_config_resource_init 76 | 77 | haproxy_config_resource.variables['frontend'] ||= {} 78 | 79 | haproxy_config_resource.variables['frontend'][new_resource.name] ||= {} 80 | haproxy_config_resource.variables['frontend'].delete(new_resource.name) if haproxy_config_resource.variables['frontend'].key?(new_resource.name) 81 | end 82 | -------------------------------------------------------------------------------- /resources/install.rb: -------------------------------------------------------------------------------- 1 | include Haproxy::Cookbook::Helpers 2 | 3 | use 'partial/_config_file' 4 | 5 | property :install_type, String, 6 | name_property: true, 7 | equal_to: %w(package source), 8 | description: 'Set the installation type' 9 | 10 | property :bin_prefix, String, 11 | default: '/usr', 12 | description: 'Set the source compile prefix' 13 | 14 | property :sensitive, [true, false], 15 | default: true, 16 | description: 'Ensure that sensitive resource data is not logged by the chef-client' 17 | 18 | # Package 19 | property :package_name, String, 20 | default: 'haproxy' 21 | 22 | property :package_version, [String, nil] 23 | 24 | property :enable_ius_repo, [true, false], 25 | default: false, 26 | description: 'Enables the IUS package repo for Centos to install versions >1.5' 27 | 28 | property :enable_epel_repo, [true, false], 29 | default: true, 30 | description: 'Enables the epel repo for RHEL based operating systems' 31 | 32 | # Source 33 | property :source_version, String, 34 | default: '2.8.5' 35 | 36 | property :source_url, String, 37 | default: lazy { "https://www.haproxy.org/download/#{source_version.to_f}/src/haproxy-#{source_version}.tar.gz" } 38 | 39 | property :source_checksum, String, 40 | default: '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' 41 | 42 | property :source_target_cpu, String, 43 | default: lazy { node['kernel']['machine'] } 44 | 45 | property :source_target_arch, String 46 | 47 | property :source_target_os, String, 48 | default: lazy { target_os(source_version) } 49 | 50 | property :use_libcrypt, [true, false], 51 | default: true 52 | 53 | property :use_pcre, [true, false], 54 | default: true 55 | 56 | property :use_promex, [true, false], 57 | default: false 58 | 59 | property :use_openssl, [true, false], 60 | default: true 61 | 62 | property :use_zlib, [true, false], 63 | default: true 64 | 65 | property :use_linux_tproxy, [true, false], 66 | default: true 67 | 68 | property :use_linux_splice, [true, false], 69 | default: true 70 | 71 | property :use_lua, [true, false], 72 | default: false 73 | 74 | property :lua_lib, String 75 | 76 | property :lua_inc, String 77 | 78 | property :ssl_lib, String 79 | 80 | property :ssl_inc, String 81 | 82 | property :use_systemd, [true, false], 83 | default: lazy { source_version.to_f >= 1.8 }, 84 | description: 'Evalues whether to use systemd based on the nodes init package' 85 | 86 | unified_mode true 87 | 88 | action_class do 89 | include Haproxy::Cookbook::ResourceHelpers 90 | end 91 | 92 | action_class do 93 | include Haproxy::Cookbook::Helpers 94 | include Haproxy::Cookbook::ResourceHelpers 95 | 96 | def compile_make_boolean(bool) 97 | bool ? '1' : '0' 98 | end 99 | end 100 | 101 | action :install do 102 | case new_resource.install_type 103 | when 'package' 104 | case node['platform_family'] 105 | when 'amazon' 106 | include_recipe 'yum-epel' if new_resource.enable_epel_repo 107 | when 'rhel' 108 | include_recipe 'yum-epel' if new_resource.enable_epel_repo 109 | 110 | if new_resource.enable_ius_repo 111 | if ius_platform_valid? 112 | puts ius_package[:url] 113 | 114 | remote_file ::File.join(Chef::Config[:file_cache_path], ius_package[:name]) do 115 | source ius_package[:url] 116 | only_if { new_resource.enable_ius_repo } 117 | end 118 | 119 | package ius_package[:name] do 120 | source ::File.join(Chef::Config[:file_cache_path], ius_package[:name]) 121 | only_if { new_resource.enable_ius_repo } 122 | end 123 | else 124 | log 'This platform is not supported by IUS, ignoring enable_ius_repo property' do 125 | level :warn 126 | end 127 | end 128 | end 129 | end 130 | 131 | package new_resource.package_name do 132 | version new_resource.package_version if new_resource.package_version 133 | end 134 | when 'source' 135 | build_essential 'compilation tools' 136 | package source_package_list 137 | 138 | remote_file 'haproxy source file' do 139 | path ::File.join(Chef::Config[:file_cache_path], "haproxy-#{new_resource.source_version}.tar.gz") 140 | source new_resource.source_url 141 | checksum new_resource.source_checksum if new_resource.source_checksum 142 | action :create 143 | end 144 | 145 | make_cmd = "make TARGET=#{new_resource.source_target_os}" 146 | make_cmd << " CPU=#{new_resource.source_target_cpu}" if property_is_set?(:source_target_cpu) 147 | make_cmd << " ARCH=#{new_resource.source_target_arch}" if property_is_set?(:source_target_arch) 148 | make_cmd << " USE_LIBCRYPT=#{compile_make_boolean(new_resource.use_libcrypt)}" 149 | make_cmd << " USE_PCRE=#{compile_make_boolean(new_resource.use_pcre)}" 150 | make_cmd << " USE_OPENSSL=#{compile_make_boolean(new_resource.use_openssl)}" 151 | make_cmd << " USE_ZLIB=#{compile_make_boolean(new_resource.use_zlib)}" 152 | make_cmd << " USE_LINUX_TPROXY=#{compile_make_boolean(new_resource.use_linux_tproxy)}" 153 | make_cmd << " USE_LINUX_SPLICE=#{compile_make_boolean(new_resource.use_linux_splice)}" 154 | make_cmd << " USE_SYSTEMD=#{compile_make_boolean(new_resource.use_systemd)}" 155 | make_cmd << " USE_LUA=#{compile_make_boolean(new_resource.use_lua)}" if new_resource.use_lua 156 | make_cmd << " USE_PROMEX=#{compile_make_boolean(new_resource.use_promex)}" if new_resource.use_promex 157 | make_cmd << " LUA_LIB=#{new_resource.lua_lib}" if property_is_set?(:lua_lib) 158 | make_cmd << " LUA_INC=#{new_resource.lua_inc}" if property_is_set?(:lua_inc) 159 | make_cmd << " SSL_LIB=#{new_resource.ssl_lib}" if property_is_set?(:ssl_lib) 160 | make_cmd << " SSL_INC=#{new_resource.ssl_inc}" if property_is_set?(:ssl_inc) 161 | extra_cmd = ' EXTRA=haproxy-systemd-wrapper' if new_resource.source_version.to_f < 1.8 162 | 163 | bash 'compile_haproxy' do 164 | cwd Chef::Config[:file_cache_path] 165 | code <<-EOH 166 | tar xzf haproxy-#{new_resource.source_version}.tar.gz 167 | cd haproxy-#{new_resource.source_version} 168 | #{make_cmd} && make install PREFIX=#{new_resource.bin_prefix} #{extra_cmd} 169 | EOH 170 | not_if "#{::File.join(new_resource.bin_prefix, 'sbin', 'haproxy')} -v | grep #{new_resource.source_version}" 171 | end 172 | end 173 | 174 | with_run_context :root do 175 | group new_resource.group 176 | 177 | user new_resource.user do 178 | home "/home/#{new_resource.user}" 179 | group new_resource.group 180 | expire_date '2050-12-31' if Chef::VERSION.to_f >= 18.0 181 | # rubocop:disable Lint/AmbiguousOperator 182 | inactive -1 if Chef::VERSION.to_f >= 18.0 183 | end 184 | end 185 | end 186 | -------------------------------------------------------------------------------- /resources/listen.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :bind, [String, Hash], 5 | default: '0.0.0.0:80', 6 | description: 'String - sets as given. Hash - joins with a space' 7 | 8 | property :mode, String, 9 | equal_to: %w(http tcp health), 10 | description: 'Set the running mode or protocol of the instance' 11 | 12 | property :maxconn, Integer, 13 | description: 'Sets the maximum per-process number of concurrent connections' 14 | 15 | property :stats, Hash, 16 | description: 'Enable stats with various options' 17 | 18 | property :http_request, [Array, String], 19 | coerce: proc { |p| Array(p).flatten }, 20 | description: 'Switch to a specific backend if/unless an ACL-based condition is matched' 21 | 22 | property :http_response, String, 23 | description: 'Switch to a specific backend if/unless an ACL-based condition is matched' 24 | 25 | property :default_backend, String, 26 | description: 'Specify the backend to use when no "use_backend" rule has been matched' 27 | 28 | property :use_backend, Array, 29 | description: 'Switch to a specific backend if/unless an ACL-based condition is matched' 30 | 31 | property :acl, Array, 32 | description: 'Access control list items' 33 | 34 | property :server, Array, 35 | description: 'Servers the listen section routes to' 36 | 37 | property :hash_type, String, 38 | equal_to: %w(consistent map-based), 39 | description: 'Specify a method to use for mapping hashes to servers' 40 | 41 | property :option, Array, 42 | description: 'Array of HAProxy option directives' 43 | 44 | unified_mode true 45 | 46 | action_class do 47 | include Haproxy::Cookbook::ResourceHelpers 48 | end 49 | 50 | action :create do 51 | haproxy_config_resource_init 52 | 53 | haproxy_config_resource.variables['listen'] ||= {} 54 | 55 | haproxy_config_resource.variables['listen'][new_resource.name] ||= {} 56 | haproxy_config_resource.variables['listen'][new_resource.name]['bind'] ||= [] 57 | 58 | if new_resource.bind.is_a?(Hash) 59 | new_resource.bind.map do |addresses, ports| 60 | Array(addresses).product(Array(ports)).each do |combo| 61 | haproxy_config_resource.variables['listen'][new_resource.name]['bind'].push(combo.join(' ').strip) 62 | end 63 | end 64 | else 65 | haproxy_config_resource.variables['listen'][new_resource.name]['bind'].push(new_resource.bind) 66 | end 67 | 68 | haproxy_config_resource.variables['listen'][new_resource.name]['mode'] = new_resource.mode if property_is_set?(:mode) 69 | haproxy_config_resource.variables['listen'][new_resource.name]['maxconn'] = new_resource.maxconn.to_s if property_is_set?(:mode) 70 | haproxy_config_resource.variables['listen'][new_resource.name]['stats'] = new_resource.stats if property_is_set?(:stats) 71 | haproxy_config_resource.variables['listen'][new_resource.name]['http_request'] = new_resource.http_request if property_is_set?(:http_request) 72 | haproxy_config_resource.variables['listen'][new_resource.name]['http_response'] = new_resource.http_response if property_is_set?(:http_response) 73 | 74 | if property_is_set?(:use_backend) 75 | haproxy_config_resource.variables['listen'][new_resource.name]['use_backend'] ||= [] 76 | haproxy_config_resource.variables['listen'][new_resource.name]['use_backend'].push(new_resource.use_backend) 77 | end 78 | 79 | if property_is_set?(:acl) 80 | haproxy_config_resource.variables['listen'][new_resource.name]['acl'] ||= [] 81 | haproxy_config_resource.variables['listen'][new_resource.name]['acl'].push(new_resource.acl) 82 | end 83 | 84 | haproxy_config_resource.variables['listen'][new_resource.name]['default_backend'] = new_resource.default_backend if property_is_set?(:default_backend) 85 | 86 | if property_is_set?(:server) 87 | haproxy_config_resource.variables['listen'][new_resource.name]['server'] ||= [] 88 | haproxy_config_resource.variables['listen'][new_resource.name]['server'].push(new_resource.server) 89 | end 90 | 91 | haproxy_config_resource.variables['listen'][new_resource.name]['hash_type'] = new_resource.hash_type if property_is_set?(:hash_type) 92 | haproxy_config_resource.variables['listen'][new_resource.name]['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 93 | 94 | if property_is_set?(:option) 95 | haproxy_config_resource.variables['listen'][new_resource.name]['option'] ||= [] 96 | haproxy_config_resource.variables['listen'][new_resource.name]['option'].concat(new_resource.option) 97 | end 98 | end 99 | 100 | action :delete do 101 | haproxy_config_resource_init 102 | 103 | haproxy_config_resource.variables['listen'] ||= {} 104 | 105 | haproxy_config_resource.variables['listen'][new_resource.name] ||= {} 106 | haproxy_config_resource.variables['listen'].delete(new_resource.name) if haproxy_config_resource.variables['listen'].key?(new_resource.name) 107 | end 108 | -------------------------------------------------------------------------------- /resources/mailer.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | 3 | property :mailer, [String, Array], 4 | coerce: proc { |p| Array(p).flatten }, 5 | description: 'Defines a mailer inside a mailers section' 6 | 7 | property :timeout, String, 8 | description: 'Defines the time available for a mail/connection to be made and send to the mail-server' 9 | 10 | unified_mode true 11 | 12 | action_class do 13 | include Haproxy::Cookbook::ResourceHelpers 14 | end 15 | 16 | action :create do 17 | haproxy_config_resource_init 18 | 19 | haproxy_config_resource.variables['mailer'] ||= {} 20 | 21 | haproxy_config_resource.variables['mailer'][new_resource.name] ||= {} 22 | haproxy_config_resource.variables['mailer'][new_resource.name]['mailer'] = new_resource.mailer if property_is_set?(:mailer) 23 | haproxy_config_resource.variables['mailer'][new_resource.name]['timeout'] = new_resource.timeout if property_is_set?(:timeout) 24 | end 25 | 26 | action :delete do 27 | haproxy_config_resource_init 28 | 29 | haproxy_config_resource.variables['mailer'] ||= {} 30 | 31 | haproxy_config_resource.variables['mailer'][new_resource.name] ||= {} 32 | haproxy_config_resource.variables['mailer'].delete(new_resource.name) if haproxy_config_resource.variables['mailer'].key?(new_resource.name) 33 | end 34 | -------------------------------------------------------------------------------- /resources/partial/_config_file.rb: -------------------------------------------------------------------------------- 1 | property :user, String, 2 | default: 'haproxy', 3 | description: 'Set to override default haproxy user, defaults to haproxy' 4 | 5 | property :group, String, 6 | default: 'haproxy', 7 | description: 'Set to override default haproxy group, defaults to haproxy' 8 | 9 | property :config_dir, String, 10 | default: '/etc/haproxy', 11 | desired_state: false, 12 | description: 'Set to override vault configuration directory' 13 | 14 | property :config_dir_mode, String, 15 | default: '0750', 16 | description: 'Set to override haproxy config dir mode, defaults to 0750' 17 | 18 | property :config_file, String, 19 | default: lazy { ::File.join(config_dir, 'haproxy.cfg') }, 20 | desired_state: false, 21 | description: 'Set to override vault configuration file, defaults to /etc/{CONFIG_DIR}/haproxy.cfg' 22 | 23 | property :config_file_mode, String, 24 | default: '0640', 25 | description: 'Set to override default haproxy config file mode, defaults to 0640' 26 | 27 | property :cookbook, String, 28 | default: 'haproxy', 29 | desired_state: false, 30 | description: 'Template source cookbook for the haproxy configuration file' 31 | 32 | property :template, String, 33 | default: 'haproxy.cfg.erb', 34 | desired_state: false, 35 | description: 'Template source file for the haproxy configuration file' 36 | -------------------------------------------------------------------------------- /resources/partial/_extra_options.rb: -------------------------------------------------------------------------------- 1 | property :extra_options, Hash, 2 | description: 'Used for setting any HAProxy directives' 3 | -------------------------------------------------------------------------------- /resources/peer.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :bind, [String, Hash], 5 | description: 'String - sets as given. Hash - joins with a space. HAProxy version >= 2.0' 6 | 7 | property :state, String, 8 | equal_to: %w(enabled disabled), 9 | description: 'Set the state of the peers' 10 | 11 | property :server, Array, 12 | description: 'Servers in the peer' 13 | 14 | property :default_bind, String, 15 | description: 'Defines the binding parameters for the local peer, excepted its address' 16 | 17 | property :default_server, String, 18 | description: 'Change default options for a server' 19 | 20 | property :table, Array, 21 | description: 'Configure a stickiness table' 22 | 23 | unified_mode true 24 | 25 | action_class do 26 | include Haproxy::Cookbook::ResourceHelpers 27 | end 28 | 29 | action :create do 30 | haproxy_config_resource_init 31 | 32 | haproxy_config_resource.variables['peer'] ||= {} 33 | 34 | haproxy_config_resource.variables['peer'][new_resource.name] ||= {} 35 | haproxy_config_resource.variables['peer'][new_resource.name]['bind'] = new_resource.bind if property_is_set?(:bind) 36 | haproxy_config_resource.variables['peer'][new_resource.name]['state'] = new_resource.state if property_is_set?(:state) 37 | 38 | if property_is_set?(:server) 39 | haproxy_config_resource.variables['peer'][new_resource.name]['server'] ||= [] 40 | haproxy_config_resource.variables['peer'][new_resource.name]['server'].push(new_resource.server) 41 | end 42 | 43 | haproxy_config_resource.variables['peer'][new_resource.name]['default_bind'] = new_resource.default_bind if property_is_set?(:default_bind) 44 | haproxy_config_resource.variables['peer'][new_resource.name]['default_server'] = new_resource.default_server if property_is_set?(:default_server) 45 | 46 | if property_is_set?(:table) 47 | haproxy_config_resource.variables['peer'][new_resource.name]['table'] ||= [] 48 | haproxy_config_resource.variables['peer'][new_resource.name]['table'].push(new_resource.table) 49 | end 50 | 51 | haproxy_config_resource.variables['peer'][new_resource.name]['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 52 | end 53 | 54 | action :delete do 55 | haproxy_config_resource_init 56 | 57 | haproxy_config_resource.variables['peer'] ||= {} 58 | 59 | haproxy_config_resource.variables['peer'][new_resource.name] ||= {} 60 | haproxy_config_resource.variables['peer'].delete(new_resource.name) if haproxy_config_resource.variables['peer'].key?(new_resource.name) 61 | end 62 | -------------------------------------------------------------------------------- /resources/resolver.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | use 'partial/_extra_options' 3 | 4 | property :nameserver, Array, 5 | description: 'DNS server description' 6 | 7 | unified_mode true 8 | 9 | action_class do 10 | include Haproxy::Cookbook::ResourceHelpers 11 | end 12 | 13 | action :create do 14 | haproxy_config_resource_init 15 | 16 | haproxy_config_resource.variables['resolvers'] ||= {} 17 | 18 | haproxy_config_resource.variables['resolvers'][new_resource.name] ||= {} 19 | 20 | if property_is_set?(:nameserver) 21 | haproxy_config_resource.variables['resolvers'][new_resource.name]['nameserver'] ||= [] 22 | haproxy_config_resource.variables['resolvers'][new_resource.name]['nameserver'].push(new_resource.nameserver) 23 | end 24 | 25 | haproxy_config_resource.variables['resolvers'][new_resource.name]['extra_options'] = new_resource.extra_options if property_is_set?(:extra_options) 26 | end 27 | 28 | action :delete do 29 | haproxy_config_resource_init 30 | 31 | haproxy_config_resource.variables['resolvers'] ||= {} 32 | 33 | haproxy_config_resource.variables['resolvers'][new_resource.name] ||= {} 34 | haproxy_config_resource.variables['resolvers'].delete(new_resource.name) if haproxy_config_resource.variables['resolvers'].key?(new_resource.name) 35 | end 36 | -------------------------------------------------------------------------------- /resources/service.rb: -------------------------------------------------------------------------------- 1 | include Haproxy::Cookbook::Helpers 2 | 3 | use 'partial/_config_file' 4 | 5 | property :bin_prefix, String, 6 | default: '/usr', 7 | description: 'Bin location of the haproxy binary, defaults to /usr' 8 | 9 | property :service_name, String, 10 | default: 'haproxy' 11 | 12 | property :systemd_unit_content, [String, Hash], 13 | default: lazy { default_systemd_unit_content }, 14 | description: 'HAProxy systemd unit contents' 15 | 16 | property :config_test, [true, false], 17 | default: true, 18 | description: 'Perform configuration file test before performing service action' 19 | 20 | property :config_test_fail_action, Symbol, 21 | equal_to: %i(raise log), 22 | default: :raise, 23 | description: 'Action to perform upon configuration test failure.' 24 | 25 | unified_mode true 26 | 27 | action_class do 28 | include Haproxy::Cookbook::Helpers 29 | 30 | def do_service_action(resource_action) 31 | with_run_context(:root) do 32 | if %i(start restart reload).include?(resource_action) 33 | begin 34 | if new_resource.config_test && ::File.exist?(new_resource.config_file) 35 | log 'Running configuration test' 36 | cmd = Mixlib::ShellOut.new("#{systemd_command(new_resource.bin_prefix)} -c -V -f #{new_resource.config_file}") 37 | cmd.run_command.error! 38 | Chef::Log.info("Configuration test passed, creating #{new_resource.service_name} #{new_resource.declared_type} resource with action #{resource_action}") 39 | elsif new_resource.config_test && !::File.exist?(new_resource.config_file) 40 | log 'Configuration test is enabled but configuration file does not exist, skipping test' do 41 | level :warn 42 | end 43 | else 44 | Chef::Log.info("Configuration test disabled, creating #{new_resource.service_name} #{new_resource.declared_type} resource with action #{resource_action}") 45 | end 46 | 47 | declare_resource(:service, new_resource.service_name).delayed_action(resource_action) 48 | rescue Mixlib::ShellOut::ShellCommandFailed 49 | if new_resource.config_test_fail_action.eql?(:log) 50 | Chef::Log.error("Configuration test failed, #{new_resource.service_name} #{resource_action} action aborted!\n\n"\ 51 | "Error\n-----\n#{cmd.stderr}") 52 | else 53 | raise "Configuration test failed, #{new_resource.service_name} #{resource_action} action aborted!\n\n"\ 54 | "Error\n-----\nAction: #{resource_action}\n#{cmd.stderr}" 55 | end 56 | end 57 | else 58 | declare_resource(:service, new_resource.service_name).delayed_action(resource_action) 59 | end 60 | end 61 | end 62 | end 63 | 64 | action :create do 65 | with_run_context :root do 66 | declare_resource(:cookbook_file, '/etc/default/haproxy') do 67 | cookbook 'haproxy' 68 | source 'haproxy-default' 69 | owner 'root' 70 | group 'root' 71 | mode '0644' 72 | end 73 | 74 | declare_resource(:systemd_unit, "#{new_resource.service_name}.service") do 75 | content new_resource.systemd_unit_content 76 | triggers_reload true 77 | action :create 78 | end 79 | end 80 | end 81 | 82 | action :delete do 83 | with_run_context :root do 84 | declare_resource(:cookbook_file, '/etc/default/haproxy').action(:delete) 85 | declare_resource(:systemd_unit, "#{new_resource.service_name}.service").action(:delete) 86 | end 87 | end 88 | 89 | %i(start stop restart reload enable disable).each do |action_type| 90 | send(:action, action_type) { do_service_action(action) } 91 | end 92 | -------------------------------------------------------------------------------- /resources/use_backend.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | 3 | property :use_backend, [String, Array], 4 | name_property: true, 5 | coerce: proc { |p| Array(p) }, 6 | description: 'Switch to a specific backend if/unless an ACL-based condition is matched' 7 | 8 | property :section, String, 9 | required: true, 10 | equal_to: %w(frontend listen backend), 11 | description: 'The section where the acl(s) should be applied' 12 | 13 | property :section_name, String, 14 | required: true, 15 | description: 'The name of the specific frontend, listen or backend section' 16 | 17 | unified_mode true 18 | 19 | action_class do 20 | include Haproxy::Cookbook::ResourceHelpers 21 | end 22 | 23 | action :create do 24 | haproxy_config_resource_init 25 | 26 | haproxy_config_resource.variables[new_resource.section] ||= {} 27 | 28 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name] ||= {} 29 | 30 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['use_backend'] ||= [] 31 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['use_backend'].push(new_resource.use_backend) 32 | end 33 | 34 | action :delete do 35 | haproxy_config_resource_init 36 | 37 | haproxy_config_resource.variables[new_resource.section] ||= {} 38 | 39 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name] ||= {} 40 | 41 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['use_backend'] ||= [] 42 | haproxy_config_resource.variables[new_resource.section][new_resource.section_name]['use_backend'].delete(new_resource.use_backend) 43 | end 44 | -------------------------------------------------------------------------------- /resources/userlist.rb: -------------------------------------------------------------------------------- 1 | use 'partial/_config_file' 2 | 3 | property :group, Hash, 4 | description: 'Adds group to the current userlist' 5 | 6 | property :user, Hash, 7 | description: 'Adds user to the current userlist' 8 | 9 | unified_mode true 10 | 11 | action_class do 12 | include Haproxy::Cookbook::ResourceHelpers 13 | end 14 | 15 | action :create do 16 | haproxy_config_resource_init 17 | 18 | haproxy_config_resource.variables['userlist'] ||= {} 19 | haproxy_config_resource.variables['userlist'][new_resource.name] ||= {} 20 | haproxy_config_resource.variables['userlist'][new_resource.name]['group'] ||= [] 21 | haproxy_config_resource.variables['userlist'][new_resource.name]['group'].push(new_resource.group) if property_is_set?(:group) 22 | haproxy_config_resource.variables['userlist'][new_resource.name]['user'] ||= [] 23 | haproxy_config_resource.variables['userlist'][new_resource.name]['user'].push(new_resource.user) if property_is_set?(:user) 24 | end 25 | 26 | action :delete do 27 | haproxy_config_resource_init 28 | 29 | haproxy_config_resource.variables['userlist'] ||= {} 30 | haproxy_config_resource.variables['userlist'][new_resource.name] ||= {} 31 | haproxy_config_resource.variables['userlist'][new_resource.name]['group'] ||= [] 32 | haproxy_config_resource.variables['userlist'][new_resource.name]['group'].delete(new_resource.group) 33 | haproxy_config_resource.variables['userlist'][new_resource.name]['user'] ||= [] 34 | haproxy_config_resource.variables['userlist'][new_resource.name]['user'].delete(new_resource.user) 35 | end 36 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'chefspec' 2 | require 'chefspec/berkshelf' 3 | 4 | RSpec.configure do |config| 5 | config.color = true # Use color in STDOUT 6 | config.formatter = :documentation # Use the specified formatter 7 | config.log_level = :error # Avoid deprecation notice SPAM 8 | end 9 | -------------------------------------------------------------------------------- /spec/unit/recipes/cache_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'haproxy_cache' do 4 | step_into :haproxy_cache, :haproxy_frontend, :haproxy_install, :haproxy_backend 5 | platform 'ubuntu' 6 | 7 | context 'create a cache, frontend and backend and verify config is created properly' do 8 | recipe do 9 | haproxy_cache 'test' do 10 | cache_name 'test-cache' 11 | total_max_size 4 12 | max_age 60 13 | end 14 | 15 | haproxy_frontend 'admin' do 16 | bind '0.0.0.0:1337' 17 | mode 'http' 18 | use_backend ['admin0 if path_beg /admin0'] 19 | extra_options('http-request' => 'cache-use test-cache', 'http-response' => 'cache-store test-cache') 20 | end 21 | 22 | haproxy_backend 'admin' do 23 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100'] 24 | end 25 | end 26 | 27 | cfg_content = [ 28 | 'cache test-cache', 29 | ' total-max-size 4', 30 | ' max-age 60', 31 | '', 32 | '', 33 | 'frontend admin', 34 | ' mode http', 35 | ' bind 0.0.0.0:1337', 36 | ' http-request cache-use test-cache', 37 | ' use_backend admin0 if path_beg /admin0', 38 | ' http-response cache-store test-cache', 39 | '', 40 | '', 41 | 'backend admin', 42 | ' server admin0 10.0.0.10:80 check weight 1 maxconn 100', 43 | ] 44 | 45 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/unit/recipes/defaults_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'haproxy_config_defaults' do 4 | step_into :haproxy_config_defaults 5 | platform 'ubuntu' 6 | 7 | context 'create a cache, frontend and backend and verify config is created properly' do 8 | recipe do 9 | haproxy_config_defaults 'default' 10 | end 11 | 12 | cfg_content = < '^(/.+\.php)(/.*)?$') 15 | end 16 | 17 | haproxy_frontend 'front-http' do 18 | bind('*:80' => '') 19 | mode 'http' 20 | use_backend ['back-dynamic if { path_reg ^/.+\.php(/.*)?$ }'] 21 | default_backend 'back-static' 22 | end 23 | 24 | haproxy_backend 'back-static' do 25 | mode 'http' 26 | server ['www A.B.C.D:80'] 27 | end 28 | 29 | haproxy_backend 'back-dynamic' do 30 | mode 'http' 31 | extra_options('use-fcgi-app' => 'php-fpm') 32 | server ['php-fpm A.B.C.D:9000 proto fcgi'] 33 | end 34 | end 35 | 36 | cfg_content = [ 37 | 'fcgi-app php-fpm', 38 | ' docroot /var/www/my-app', 39 | ' index index.php', 40 | ' log-stderr global', 41 | ' option keep-conn', 42 | ' path-info \^\(\/\.\+\\\.php\)\(\/\.\*\)\?\$', 43 | '', 44 | '', 45 | 'frontend front-http', 46 | ' mode http', 47 | ' default_backend back-static', 48 | ' bind \*:80', 49 | ' use_backend back-dynamic if \{ path_reg \^\/\.\+\\\.php\(\/\.\*\)\?\$ \}', 50 | '', 51 | '', 52 | 'backend back-static', 53 | ' mode http', 54 | ' server www A.B.C.D:80', 55 | '', 56 | '', 57 | 'backend back-dynamic', 58 | ' mode http', 59 | ' server php-fpm A.B.C.D:9000 proto fcgi', 60 | ' use-fcgi-app php-fpm', 61 | ] 62 | 63 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/unit/recipes/frontend_backend_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'haproxy_frontend' do 4 | step_into :haproxy_frontend, :haproxy_install, :haproxy_backend 5 | platform 'ubuntu' 6 | 7 | context 'create frontend and backend with http-request rule placed before use_backend' do 8 | recipe do 9 | haproxy_frontend 'admin' do 10 | bind '0.0.0.0:1337' => '' 11 | mode 'http' 12 | use_backend ['admin0 if path_beg /admin0'] 13 | extra_options('http-request' => 'add-header Test Value') 14 | end 15 | 16 | haproxy_backend 'admin' do 17 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100'] 18 | end 19 | end 20 | 21 | cfg_content = [ 22 | 'frontend admin', 23 | ' mode http', 24 | ' bind 0.0.0.0:1337', 25 | ' http-request add-header Test Value', 26 | ' use_backend admin0 if path_beg /admin0', 27 | '', 28 | '', 29 | 'backend admin', 30 | ' server admin0 10.0.0.10:80 check weight 1 maxconn 100', 31 | ] 32 | 33 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 34 | it { is_expected.not_to render_file('/etc/haproxy/haproxy.cfg').with_content(%r{use_backend admin0 if path_beg /admin0.*http-request add-header Test Value}m) } 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/unit/recipes/global_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'haproxy_config_global' do 4 | step_into :haproxy_config_global 5 | platform 'ubuntu' 6 | 7 | context 'create haproxy config global' do 8 | recipe do 9 | haproxy_config_global 'global' 10 | end 11 | 12 | cfg_content = < '' 11 | mode 'http' 12 | stats uri: '/', 13 | realm: 'Haproxy-Statistics', 14 | auth: 'user:pwd' 15 | http_request 'add-header X-Proto http' 16 | http_response 'set-header Expires %[date(3600),http_date]' 17 | default_backend 'servers' 18 | extra_options('bind-process' => 'odd') 19 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100', 20 | 'admin1 10.0.0.10:80 check weight 1 maxconn 100'] 21 | end 22 | end 23 | 24 | cfg_content = [ 25 | 'listen admin', 26 | ' mode http', 27 | ' bind 0.0.0.0:1337', 28 | ' stats uri /', 29 | ' stats realm Haproxy-Statistics', 30 | ' stats auth user:pwd', 31 | ' http-request add-header X-Proto http', 32 | ' http-response set-header Expires %\[date\(3600\),http_date]', 33 | ' default_backend servers', 34 | ' bind-process odd', 35 | ' server admin0 10.0.0.10:80 check weight 1 maxconn 100', 36 | ' server admin1 10.0.0.10:80 check weight 1 maxconn 100', 37 | ] 38 | 39 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 40 | end 41 | 42 | context 'extra options hash with disabled option' do 43 | recipe do 44 | haproxy_install 'package' 45 | 46 | haproxy_listen 'disabled' do 47 | bind '0.0.0.0:1337' 48 | mode 'http' 49 | extra_options('disabled': '') 50 | end 51 | end 52 | 53 | cfg_content = [ 54 | 'listen disabled', 55 | ' mode http', 56 | ' bind 0.0.0.0:1337', 57 | ' disabled', 58 | ] 59 | 60 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 61 | end 62 | 63 | context 'extra options http-request rule should be placed before use_backend rule' do 64 | recipe do 65 | haproxy_install 'package' 66 | 67 | haproxy_listen 'use_backend' do 68 | bind '0.0.0.0:1337' 69 | mode 'http' 70 | use_backend ['admin0 if path_beg /admin0'] 71 | extra_options('http-request' => 'add-header Test Value') 72 | end 73 | end 74 | 75 | cfg_content = [ 76 | 'listen use_backend', 77 | ' mode http', 78 | ' bind 0.0.0.0:1337', 79 | ' http-request add-header Test Value', 80 | ' use_backend admin0 if path_beg /admin0', 81 | ] 82 | 83 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 84 | it { is_expected.not_to render_file('/etc/haproxy/haproxy.cfg').with_content(%r{use_backend admin0 if path_beg /admin0.*http-request add-header Test Value}m) } 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /spec/unit/recipes/mailer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'haproxy_mailer' do 4 | step_into :haproxy_mailer, :haproxy_frontend, :haproxy_install, :haproxy_backend 5 | platform 'ubuntu' 6 | 7 | context 'create a mailer, frontend and backend and verify config is created properly' do 8 | recipe do 9 | haproxy_mailer 'mymailer' do 10 | mailer ['smtp1 192.168.0.1:587', 'smtp2 192.168.0.2:587'] 11 | timeout '20s' 12 | end 13 | 14 | haproxy_frontend 'admin' do 15 | bind '0.0.0.0:1337' 16 | mode 'http' 17 | use_backend ['admin0 if path_beg /admin0'] 18 | end 19 | 20 | haproxy_backend 'admin' do 21 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100'] 22 | extra_options('email-alert' => [ 'mailers mymailers', 23 | 'from test1@horms.org', 24 | 'to test2@horms.org' ]) 25 | end 26 | end 27 | 28 | cfg_content = [ 29 | 'mailers mymailer', 30 | ' mailer smtp1 192.168.0.1:587', 31 | ' mailer smtp2 192.168.0.2:587', 32 | ' timeout mail 20s', 33 | '', 34 | '', 35 | 'frontend admin', 36 | ' mode http', 37 | ' bind 0.0.0.0:1337', 38 | ' use_backend admin0 if path_beg /admin0', 39 | '', 40 | '', 41 | 'backend admin', 42 | ' server admin0 10.0.0.10:80 check weight 1 maxconn 100', 43 | ' email-alert mailers mymailers', 44 | ' email-alert from test1@horms.org', 45 | ' email-alert to test2@horms.org', 46 | ] 47 | 48 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /spec/unit/recipes/peer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'haproxy_peer' do 4 | step_into :haproxy_peer, :haproxy_frontend, :haproxy_install, :haproxy_backend 5 | platform 'ubuntu' 6 | 7 | context 'create a peers section, frontend and backend and verify config is created properly' do 8 | recipe do 9 | haproxy_peer 'mypeers' do 10 | bind('0.0.0.0:1336' => '') 11 | default_server 'ssl verify none' 12 | server ['hostA 127.0.0.10:10000'] 13 | end 14 | 15 | haproxy_frontend 'admin' do 16 | bind '0.0.0.0:1337' 17 | mode 'http' 18 | use_backend ['admin0 if path_beg /admin0'] 19 | end 20 | 21 | haproxy_backend 'admin' do 22 | extra_options('stick-table' => 'type string len 32 size 100k expire 30m peers mypeers') 23 | server ['admin0 10.0.0.10:80 check weight 1 maxconn 100'] 24 | end 25 | end 26 | 27 | cfg_content = [ 28 | 'peers mypeers', 29 | ' bind 0.0.0.0:1336', 30 | ' server hostA 127.0.0.10:10000', 31 | ' default-server ssl verify none', 32 | '', 33 | '', 34 | 'frontend admin', 35 | ' mode http', 36 | ' bind 0.0.0.0:1337', 37 | ' use_backend admin0 if path_beg /admin0', 38 | '', 39 | '', 40 | 'backend admin', 41 | ' server admin0 10.0.0.10:80 check weight 1 maxconn 100', 42 | ' stick-table type string len 32 size 100k expire 30m peers mypeers', 43 | ] 44 | 45 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /templates/default/haproxy.cfg.erb: -------------------------------------------------------------------------------- 1 | <% unless nil_or_empty?(@global) %> 2 | global 3 | user <%= @global['user'] %> 4 | group <%= @global['group'] %> 5 | <% if @global['pid_file'] -%> 6 | pidfile <%= @global['pid_file'] %> 7 | <% end %> 8 | <% if @global['log'] && @global['log'].is_a?(Array)-%> 9 | <% @global['log'].each do | logvar | -%> 10 | <% if logvar && logvar.is_a?(Array)-%> 11 | <% logvar.each do | log | -%> 12 | log <%= log %> 13 | <% end -%> 14 | <% else -%> 15 | log <%= logvar %> 16 | <% end -%> 17 | <% end -%> 18 | <% end -%> 19 | <% if @global['log_tag'] -%> 20 | log-tag <%= @global['log_tag'] %> 21 | <% end -%> 22 | <% if @global['chroot'] -%> 23 | chroot <%= @global['chroot'] %> 24 | <% end -%> 25 | <% if @global['daemon'].eql? 'true' -%> 26 | daemon 27 | <% end -%> 28 | <%= @global['debug_option'] %> 29 | <% @global['stats']&.each do |option, value| -%> 30 | stats <%= option %> <%= value %> 31 | <% end -%> 32 | <% unless nil_or_empty?(@global['maxconn']) -%> 33 | maxconn <%= @global['maxconn'] %> 34 | <% end -%> 35 | <% if @global['pidfile'] -%> 36 | pidfile <%= @global['pidfile'] %> 37 | <% end -%> 38 | <% unless nil_or_empty?(@global['tuning']) %> 39 | <% @global['tuning'].each do | option, value | -%> 40 | tune.<%= option %> <%= value %> 41 | <% end -%> 42 | <% end -%> 43 | <% unless nil_or_empty?(@global['extra_options']) -%> 44 | <% @global['extra_options'].each do | option, value | -%> 45 | <% if value.is_a?(Array) %> 46 | <% value.each do | array_element | %> 47 | <%= option %> <%= array_element %> 48 | <% end -%> 49 | <% else %> 50 | <%= option %> <%= value %> 51 | <% end -%> 52 | <% end -%> 53 | <% end -%> 54 | <% end -%> 55 | <% unless nil_or_empty?(@resolvers) %> 56 | <% @resolvers.each do |resolver, r | %> 57 | 58 | 59 | resolvers <%= resolver %> 60 | <% unless nil_or_empty?(r['nameserver']) %> 61 | <% r['nameserver'].each do | s |%> 62 | <% s.each do |nameserver|%> 63 | nameserver <%= nameserver %> 64 | <% end -%> 65 | <% end -%> 66 | <% end -%> 67 | <% r['extra_options'].each do | option, value | -%> 68 | <% if value.is_a?(Array) %> 69 | <% value.each do | array_element | %> 70 | <%= option %> <%= array_element %> 71 | <% end -%> 72 | <% else %> 73 | <%= option %> <%= value %> 74 | <% end -%> 75 | <% end -%> 76 | <% end -%> 77 | <% end -%> 78 | <% unless nil_or_empty?(@defaults) %> 79 | 80 | 81 | defaults 82 | <% @defaults['timeout'].each do | key, timeout | -%> 83 | timeout <%= key %> <%= timeout %> 84 | <% end -%> 85 | log <%= @defaults['log'] %> 86 | mode <%= @defaults['mode'] %> 87 | <% unless nil_or_empty?(@defaults['balance']) -%> 88 | balance <%= @defaults['balance'] %> 89 | <% end -%> 90 | <% if @defaults['hash_type'] -%> 91 | hash-type <%= @defaults['hash_type'] %> 92 | <% end -%> 93 | <% @defaults['option'].each do | option | -%> 94 | option <%= option %> 95 | <% end -%> 96 | <% unless nil_or_empty?(@defaults['maxconn']) -%> 97 | maxconn <%= @defaults['maxconn'] %> 98 | <% end -%> 99 | <% unless nil_or_empty?(@defaults['retries']) -%> 100 | retries <%= @defaults['retries'] %> 101 | <% end -%> 102 | <% @defaults['stats']&.each do |option, value| -%> 103 | stats <%= option %> <%= value %> 104 | <% end -%> 105 | <% unless nil_or_empty?(@defaults['extra_options']) %> 106 | <% @defaults['extra_options'].each do | option, value | -%> 107 | <% if value.is_a?(Array) %> 108 | <% value.each do | array_element | %> 109 | <%= option %> <%= array_element %> 110 | <% end -%> 111 | <% else %> 112 | <%= option %> <%= value %> 113 | <% end -%> 114 | <% end -%> 115 | <% end -%> 116 | <% end -%> 117 | <% unless nil_or_empty?(@cache) %> 118 | <% @cache.each do |cache, c | %> 119 | 120 | 121 | cache <%= cache %> 122 | <% unless nil_or_empty?(c['total_max_size']) -%> 123 | total-max-size <%= c['total_max_size'] %> 124 | <% end -%> 125 | <% unless nil_or_empty?(c['max_object_size']) %> 126 | max-object-size <%= c['max_object_size'] %> 127 | <% end -%> 128 | <% unless nil_or_empty?(c['max_age']) %> 129 | max-age <%= c['max_age'] %> 130 | <% end -%> 131 | <% end # cache loop -%> 132 | <% end # cache -%> 133 | <% unless nil_or_empty?(@userlist) %> 134 | <% @userlist.each do |userlist, u| %> 135 | 136 | 137 | userlist <%= userlist %> 138 | <% u.each do |type,i| -%> 139 | <% i.each do |item| -%> 140 | <% item.each do |k,v| %> 141 | <%= type %> <%=k%> <%= v %> 142 | <% end -%> 143 | <% end -%> 144 | <% end -%> 145 | <% end -%> 146 | <% end -%> 147 | <% unless nil_or_empty?(@peer) %> 148 | <% @peer.each do |peer, pv | %> 149 | 150 | peers <%= peer %> 151 | <% if pv['bind'].is_a?(Hash) -%> 152 | <% pv['bind'].each do |k, v| -%> 153 | bind <%= "#{k} #{v}".strip %> 154 | <% end -%> 155 | <% else -%> 156 | bind <%= pv['bind'] %> 157 | <% end -%> 158 | <% unless nil_or_empty?(pv['state']) %> 159 | <%= pv['state'] %> 160 | <% end -%> 161 | <% unless nil_or_empty?(pv['server']) %> 162 | <% pv['server'].each do | s |%> 163 | <% s.each do |server|%> 164 | server <%= server %> 165 | <% end -%> 166 | <% end -%> 167 | <% end -%> 168 | <% unless nil_or_empty?(pv['default_bind']) %> 169 | default-bind <%= pv['default_bind'] %> 170 | <% end -%> 171 | <% unless nil_or_empty?(pv['default_server']) %> 172 | default-server <%= pv['default_server'] %> 173 | <% end -%> 174 | <% unless nil_or_empty?(pv['table']) %> 175 | <% pv['table'].each do | t |%> 176 | <% t.each do |table|%> 177 | table <%= table %> 178 | <% end -%> 179 | <% end -%> 180 | <% end -%> 181 | <% unless nil_or_empty?(pv['extra_options']) %> 182 | <% pv['extra_options'].each do | key, value |%> 183 | <% if value.is_a?(Array) %> 184 | <% value.each do | array_element | %> 185 | <%= key %> <%= array_element %> 186 | <% end -%> 187 | <% else %> 188 | <%= key %> <%= value %> 189 | <% end -%> 190 | <% end -%> 191 | <% end -%> 192 | <% end # peers loop -%> 193 | <% end # peers -%> 194 | <% unless nil_or_empty?(@mailer) %> 195 | <% @mailer.each do |mailer, m | %> 196 | 197 | mailers <%= mailer %> 198 | <% unless nil_or_empty?(m['mailer']) -%> 199 | <% m['mailer'].each do |mail| -%> 200 | mailer <%= mail %> 201 | <% end -%> 202 | <% end -%> 203 | <% unless nil_or_empty?(m['timeout']) %> 204 | timeout mail <%= m['timeout'] %> 205 | <% end -%> 206 | <% end # mailers loop -%> 207 | <% end # mailers -%> 208 | <% unless nil_or_empty?(@fastcgi) %> 209 | <% @fastcgi.each do |fastcgi, f | %> 210 | 211 | 212 | fcgi-app <%= fastcgi %> 213 | <% unless nil_or_empty?(f['docroot']) %> 214 | docroot <%= f['docroot'] %> 215 | <% end -%> 216 | <% unless nil_or_empty?(f['index']) %> 217 | index <%= f['index'] %> 218 | <% end -%> 219 | <% unless nil_or_empty?(f['log_stderr']) %> 220 | log-stderr <%= f['log_stderr'] %> 221 | <% end -%> 222 | <% unless nil_or_empty?(f['option']) %> 223 | <% f['option'].each do | option |%> 224 | option <%= option %> 225 | <% end -%> 226 | <% end -%> 227 | <% unless nil_or_empty?(f['extra_options']) %> 228 | <% f['extra_options'].each do | key, value | %> 229 | <% unless key == 'http-request' %> 230 | <% if value.is_a?(Array) %> 231 | <% value.each do | array_element | %> 232 | <%= key %> <%= array_element %> 233 | <% end -%> 234 | <% else %> 235 | <%= key %> <%= value %> 236 | <% end -%> 237 | <% end -%> 238 | <% end -%> 239 | <% end -%> 240 | <% end # fastcgi loop -%> 241 | <% end # fastcgi -%> 242 | <% unless nil_or_empty?(@frontend) %> 243 | <% @frontend.each do |frontend, f | %> 244 | 245 | 246 | frontend <%= frontend %> 247 | <% unless nil_or_empty?(f['mode']) -%> 248 | mode <%= f['mode'] %> 249 | <% end -%> 250 | <% unless nil_or_empty?(f['default_backend']) %> 251 | default_backend <%= f['default_backend'] %> 252 | <% end -%> 253 | <% f['bind'].each do |binding| -%> 254 | bind <%= binding %> 255 | <% end -%> 256 | <% unless nil_or_empty?(f['maxconn']) -%> 257 | maxconn <%= f['maxconn'] %> 258 | <% end -%> 259 | <% f['stats']&.each do |option, value| -%> 260 | stats <%= option %> <%= value %> 261 | <% end -%> 262 | <% unless nil_or_empty?(f['acl']) %> 263 | <% f['acl'].flatten.uniq.each do | acl |%> 264 | acl <%= acl %> 265 | <% end -%> 266 | <% end -%> 267 | <% unless nil_or_empty?(f['extra_options']) %> 268 | <% f['extra_options'].each do | key, value | %> 269 | <% if key == 'http-request' %> 270 | <% if value.is_a?(Array) %> 271 | <% value.each do | array_element | %> 272 | <%= key %> <%= array_element %> 273 | <% end -%> 274 | <% else %> 275 | <%= key %> <%= value %> 276 | <% end -%> 277 | <% end -%> 278 | <% end -%> 279 | <% end -%> 280 | <% unless nil_or_empty?(f['use_backend']) %> 281 | <% f['use_backend'].flatten.uniq.each do | backend |%> 282 | use_backend <%= backend %> 283 | <% end -%> 284 | <% end -%> 285 | <% unless nil_or_empty?(f['option']) %> 286 | <% f['option'].each do | option |%> 287 | option <%= option %> 288 | <% end -%> 289 | <% end -%> 290 | <% unless nil_or_empty?(f['extra_options']) %> 291 | <% f['extra_options'].each do | key, value | %> 292 | <% unless key == 'http-request' %> 293 | <% if value.is_a?(Array) %> 294 | <% value.each do | array_element | %> 295 | <%= key %> <%= array_element %> 296 | <% end -%> 297 | <% else %> 298 | <%= key %> <%= value %> 299 | <% end -%> 300 | <% end -%> 301 | <% end -%> 302 | <% end -%> 303 | <% end # frontend loop -%> 304 | <% end # frontend -%> 305 | <% unless nil_or_empty?(@backend) %> 306 | <% @backend.each do | key, backend | %> 307 | 308 | 309 | backend <%= key %> 310 | <% unless nil_or_empty?(backend['mode']) -%> 311 | mode <%= backend['mode'] %> 312 | <% end -%> 313 | <% unless nil_or_empty?(backend['server']) %> 314 | <% backend['server'].each do | s |%> 315 | <% s.each do |server|%> 316 | server <%= server %> 317 | <% end -%> 318 | <% end -%> 319 | <% end -%> 320 | <% unless nil_or_empty?(backend['acl']) %> 321 | <% backend['acl'].flatten.uniq.each do | acl |%> 322 | acl <%= acl %> 323 | <% end -%> 324 | <% end -%> 325 | <% unless nil_or_empty?(backend['option']) %> 326 | <% backend['option'].each do | option |%> 327 | option <%= option %> 328 | <% end -%> 329 | <% end -%> 330 | <% unless nil_or_empty?(backend['tcp_request']) %> 331 | <% backend['tcp_request'].each do | tcp_request |%> 332 | <% tcp_request.each do | tcp_request | %> 333 | tcp-request <%= tcp_request %> 334 | <% end -%> 335 | <% end -%> 336 | <% end -%> 337 | <% if backend['hash_type'] -%> 338 | hash-type <%= backend['hash_type'] %> 339 | <% end -%> 340 | <% unless nil_or_empty?(backend['extra_options']) %> 341 | <% backend['extra_options'].each do | key, value |%> 342 | <% if value.is_a?(Array) %> 343 | <% value.each do | array_element | %> 344 | <%= key %> <%= array_element %> 345 | <% end -%> 346 | <% else %> 347 | <%= key %> <%= value %> 348 | <% end -%> 349 | <% end -%> 350 | <% end -%> 351 | <% end # backend loop -%> 352 | <% end # backend -%> 353 | <% unless nil_or_empty?(@listen) %> 354 | <% @listen.each do | key, listen |%> 355 | 356 | 357 | listen <%= key %> 358 | <% unless nil_or_empty?(listen['mode']) -%> 359 | mode <%= listen['mode']%> 360 | <% end -%> 361 | <% listen['bind'].each do |binding| -%> 362 | bind <%= binding %> 363 | <% end -%> 364 | <% unless nil_or_empty?(listen['maxconn']) -%> 365 | maxconn <%= listen['maxconn']%> 366 | <% end -%> 367 | <% listen['stats']&.each do |option, value| -%> 368 | stats <%= option %> <%= value %> 369 | <% end -%> 370 | <% unless nil_or_empty?(listen['acl']) %> 371 | <% listen['acl'].flatten.uniq.each do | acl |%> 372 | acl <%= acl %> 373 | <% end -%> 374 | <% end -%> 375 | <% if listen['http_request'] -%> 376 | <% listen['http_request'].each do |http_request| %> 377 | http-request <%= http_request %> 378 | <% end -%> 379 | <% end %> 380 | <% if listen['http_response'] -%> 381 | http-response <%= listen['http_response'] %> 382 | <% end %> 383 | <% if listen['default_backend'] -%> 384 | default_backend <%= listen['default_backend'] %> 385 | <% end %> 386 | <% unless nil_or_empty?(listen['option']) %> 387 | <% listen['option'].each do | option |%> 388 | option <%= option %> 389 | <% end -%> 390 | <% end -%> 391 | <% unless nil_or_empty?(listen['extra_options']) %> 392 | <% listen['extra_options'].each do | key, value | %> 393 | <% if key == 'http-request' %> 394 | <% if value.is_a?(Array) %> 395 | <% value.each do | array_element | %> 396 | <%= key %> <%= array_element %> 397 | <% end -%> 398 | <% else %> 399 | <%= key %> <%= value %> 400 | <% end -%> 401 | <% end -%> 402 | <% end -%> 403 | <% end -%> 404 | <% unless nil_or_empty?(listen['use_backend']) %> 405 | <% listen['use_backend'].flatten.uniq.each do | backend |%> 406 | use_backend <%= backend %> 407 | <% end -%> 408 | <% end -%> 409 | <% unless nil_or_empty?(listen['extra_options']) %> 410 | <% listen['extra_options'].each do | key, value | %> 411 | <% unless key == 'http-request' %> 412 | <% if value.is_a?(Array) %> 413 | <% value.each do | array_element | %> 414 | <%= key %> <%= array_element %> 415 | <% end -%> 416 | <% else %> 417 | <%= key %> <%= value %> 418 | <% end -%> 419 | <% end -%> 420 | <% end -%> 421 | <% end -%> 422 | <% listen['server']&.each do | s |%> 423 | <% s.each do |server|%> 424 | server <%= server %> 425 | <% end -%> 426 | <% end -%> 427 | <% if listen['hash_type'] -%> 428 | hash-type <%= listen['hash_type'] %> 429 | <% end -%> 430 | <% end # listen loop -%> 431 | <% end # listen -%> 432 | -------------------------------------------------------------------------------- /test/cookbooks/test/files/default/example.com.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDgTCCAmmgAwIBAgIJANGu+0IckGCpMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV 3 | BAYTAlVTMQswCQYDVQQIDAJUWDEPMA0GA1UEBwwGQXVzdGluMRQwEgYDVQQKDAtF 4 | eGFtcGxlLUNvbTEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMTcwNTMxMTYyNTEz 5 | WhcNMTgwNTMxMTYyNTEzWjBXMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVFgxDzAN 6 | BgNVBAcMBkF1c3RpbjEUMBIGA1UECgwLRXhhbXBsZS1Db20xFDASBgNVBAMMC2V4 7 | YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArrv4/A8N 8 | lvH5d1R2CTyiEMjsA4XGOyQe7t0Bu4IvPepR4pgE799LlBgifSLSkfohya7dYeLs 9 | E21cHrORZsP/xbzY+67NtAmyZt5wVB968aBS1sNyQbMQGW2CnYcCoIq69b06SbI+ 10 | Qehpm3t8x5EPuBHB4njirLBneFi0ehjCyln547GwylyMeZKBMFJs+gQiJcoOwdmk 11 | dA64JIPMdcZolcyCpQXKdRXHtVEWzxVBIsTmvoeqnfjpYWNHXAkSizthK4IDD2Oz 12 | WyrDghGvm824vFXQjf0eSrscrWESocqeVPaCp980/PKwmTFn7vqTzhnbKZQEO3al 13 | Rpzw1+oV7joIGwIDAQABo1AwTjAdBgNVHQ4EFgQUndrB5eKHyeRirFwF2Zowgt8e 14 | pFcwHwYDVR0jBBgwFoAUndrB5eKHyeRirFwF2Zowgt8epFcwDAYDVR0TBAUwAwEB 15 | /zANBgkqhkiG9w0BAQsFAAOCAQEAh/B1qolafw5gI4wdC6gqMYtGQfuX0DDQuxp7 16 | nPpTQf0LgtAVR6Hcxap0pWDny2yZUWwOW2AERcg9qfE0RQ3O3dRB3ighJePXZunj 17 | l5el6/QFccFuXIQp9x+D4DhePyevTno3XVhzGxLZx/fcB6S4c/ZqmP24AeO4xTbC 18 | 5uBaB0OveiFEyDYHRjqigjAL61zKxHu1Cl766IAqZeRV1ZeBYEStqgGcqiG7nCuV 19 | Ni5AGwYwfA2CEbt9Z2GAzpSwP0d7zR8CwsAoNdk0YHATZ+CaytMTbJjTXoqL8QMW 20 | ABMgmNjpVAGH7LV9sSNbqtP4YyMNDm5Pofm6S/GvwVtgh13ttQ== 21 | -----END CERTIFICATE----- 22 | -----BEGIN PRIVATE KEY----- 23 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCuu/j8Dw2W8fl3 24 | VHYJPKIQyOwDhcY7JB7u3QG7gi896lHimATv30uUGCJ9ItKR+iHJrt1h4uwTbVwe 25 | s5Fmw//FvNj7rs20CbJm3nBUH3rxoFLWw3JBsxAZbYKdhwKgirr1vTpJsj5B6Gmb 26 | e3zHkQ+4EcHieOKssGd4WLR6GMLKWfnjsbDKXIx5koEwUmz6BCIlyg7B2aR0Drgk 27 | g8x1xmiVzIKlBcp1Fce1URbPFUEixOa+h6qd+OlhY0dcCRKLO2ErggMPY7NbKsOC 28 | Ea+bzbi8VdCN/R5KuxytYRKhyp5U9oKn3zT88rCZMWfu+pPOGdsplAQ7dqVGnPDX 29 | 6hXuOggbAgMBAAECggEAUK0jiaWdnar9hrYthZhEL8HFDt9OJnJIAfty2FOEYm70 30 | /c04wlPz/l2iVuqkFJhLz2X4e0CdxV6B4P8BzFQEnRTTjmkoOs8bWtmrPXwHdNaU 31 | SOqWr3TwovzoCLmUYfGL3vhOmEY+7olTcWFzvGTiwBca0OkFp7wPGgbC1XjnPyvG 32 | Vii5W2+h2N+ecRc1OT/+elF9xSSuuZdmEzzCHnAN0HqLUau6tkf83jUXitTGA07H 33 | 4822V9YDQxpAckLCklnBCQGof11mYXN4k8BDzyR6VljNvV42em3IuXUzk0daAWF0 34 | VRB5PzU27JNVZ6ftViFNLfCTdSO9LACpEbvnrlUUWQKBgQDfdhx3F0EmVQRGHs5k 35 | zjBeci2O6zSWns9uVLpGS7nb2M6CZWb60qEcuvuIS1BiXrSyr1/RIcv4IocPLMgd 36 | esRMBuqqdg0Xl8hr2eRJLpqK7i5ZIMFYI6+a9Q6fg4wwo19AUVm/EYTg8/g/+MPF 37 | uKvob76S8Hg3E36OOV8pOO/9RwKBgQDILXqQCRsiY3Q0RvqzqE9jeLpa4Oc7R4T0 38 | BNfV/EcCHKH9EMz5xEp996tnyL49FsgEujWP/GE8DxbNZyQEGxR//5r60QIGS+aT 39 | mKMaeZ4Aw6Dczg/bouBDzjfKgBz3M3x+QgG7Mfm1mzzpoofP+EluT9QPZrvHE8ZU 40 | dBSnmjw4jQKBgQDRYRsU3141K43gofbj72rU5AkaE/rncpCMIamUOlpAy6nb9mWC 41 | eZ9qiy0qLN95/KE1mCugihlTPA7uwhgTvzd0wTpaVFi6FYc+vyAvDhLSQJB/BLkE 42 | /BMLj7iO8DSIUlvqqQ79f83Q9ehTEKVnezzgguu/RMBvYr2/R7SJrIb5+wKBgQCE 43 | fRVRn7VF3W1b7F6h6hQhUhaFb7Wblop4t3vjNUYKL8lHJYeFCFYFaZcY6dR/ukRI 44 | XLZ2xiPVDGebK1i7HvFChnqc5xjf8fx6U9wf+b6J4vDlM71rMTIdrq9eZ8zEEF+l 45 | cSqUK0+K02RNfjVFgJ+ZU1yXlPdTm9L4spu5EmwpQQKBgGkyJ4u9SaBI5lEUzVu4 46 | 8oS+IEo4X6gwL/QMROfxNEyEYAvPgPwDj9efkIWiDUQxkj+T/KbLpLI51aB/19/+ 47 | evVC9kl8vNoeSx4iy2hMgNQsw1dR3ifuDyNFBZf1FnRSJR2VQQ7ATothoqcaON61 48 | xnIb68ht/Ovw4pAr1vLjgmT7 49 | -----END PRIVATE KEY----- 50 | -------------------------------------------------------------------------------- /test/cookbooks/test/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'test' 2 | maintainer 'Heavy Water Software Inc.' 3 | maintainer_email 'ops@hw-ops.com' 4 | license 'Apache-2.0' 5 | description 'Testing cookbook for haproxy' 6 | version '0.0.1' 7 | depends 'haproxy' 8 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_2.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'package' 4 | 5 | directory '/etc/haproxy/errors' do 6 | user 'haproxy' 7 | group 'haproxy' 8 | end 9 | 10 | error_file = '/etc/haproxy/errors/403.http' 11 | 12 | file '403' do 13 | path error_file 14 | content <<-FILE 15 | HTTP/1.1 403 Forbidden 16 | Cache-Control: no-cache 17 | Connection: close 18 | Content-Type: text/html 19 | 20 | 21 | 22 | 23 |

403 Forbidden

24 |

Sorry, but you are not authorized to view this page.

25 | 26 | 27 | FILE 28 | end 29 | 30 | haproxy_config_global 'global' do 31 | daemon false 32 | maxconn 4096 33 | chroot '/var/lib/haproxy' 34 | stats socket: '/var/lib/haproxy/haproxy.stat mode 600 level admin', 35 | timeout: '2m' 36 | end 37 | 38 | haproxy_config_defaults 'defaults' do 39 | timeout connect: '5s', 40 | client: '50s', 41 | server: '50s' 42 | log 'global' 43 | retries 3 44 | end 45 | 46 | haproxy_frontend 'http' do 47 | bind '0.0.0.0:80' 48 | default_backend 'rrhost' 49 | maxconn 2000 50 | use_backend ['gina if gina_host', 51 | 'rrhost if rrhost_host', 52 | 'abuser if source_is_abuser', 53 | 'tiles_public if tile_host'] 54 | option %w(dontlognull forwardfor) 55 | acl ['kml_request path_reg -i /kml/', 56 | 'bbox_request path_reg -i /bbox/', 57 | 'gina_host hdr(host) -i foo.bar.com', 58 | 'rrhost_host hdr(host) -i dave.foo.bar.com foo.foo.com', 59 | 'source_is_abuser src_get_gpc0(http) gt 0', 60 | 'tile_host hdr(host) -i dough.foo.bar.com', 61 | ] 62 | 63 | stats uri: '/haproxy?stats' 64 | 65 | extra_options 'stick-table' => 'type ip size 200k expire 10m store gpc0', 66 | 'tcp-request' => 'connection track-sc1 src if !source_is_abuser' 67 | end 68 | 69 | haproxy_backend 'tiles_public' do 70 | server ['tile0 10.0.0.10:80 check weight 1 maxconn 100', 71 | 'tile1 10.0.0.10:80 check weight 1 maxconn 100'] 72 | tcp_request ['content track-sc2 src', 73 | 'content reject if conn_rate_abuse mark_as_abuser'] 74 | option %w(dontlognull forwardfor) 75 | acl ['conn_rate_abuse sc2_conn_rate gt 3000', 76 | 'data_rate_abuse sc2_bytes_out_rate gt 20000000', 77 | 'mark_as_abuser sc1_inc_gpc0 gt 0', 78 | ] 79 | extra_options( 80 | 'stick-table' => 'type ip size 200k expire 2m store conn_rate(60s),bytes_out_rate(60s)', 81 | 'http-request' => 'set-header X-Public-User yes' 82 | ) 83 | end 84 | 85 | haproxy_backend 'abuser' do 86 | extra_options 'errorfile' => "403 #{error_file}" 87 | end 88 | 89 | haproxy_backend 'rrhost' do 90 | server ['tile0 10.0.0.10:80 check weight 1 maxconn 100', 91 | 'tile1 10.0.0.10:80 check weight 1 maxconn 100'] 92 | end 93 | 94 | haproxy_backend 'gina' do 95 | server ['tile0 10.0.0.10:80 check weight 1 maxconn 100', 96 | 'tile1 10.0.0.10:80 check weight 1 maxconn 100'] 97 | end 98 | 99 | haproxy_service 'haproxy' do 100 | action %i(create enable start) 101 | end 102 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_3.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'package' 4 | 5 | haproxy_config_global '' do 6 | chroot '/var/lib/haproxy' 7 | daemon true 8 | maxconn 256 9 | log ['/dev/log local0', '/dev/log local1 notice'] 10 | log_tag 'WARDEN' 11 | pidfile '/var/run/haproxy.pid' 12 | stats socket: '/var/lib/haproxy/stats level admin' 13 | tuning 'bufsize' => '262144' 14 | end 15 | 16 | haproxy_config_defaults 'defaults' do 17 | mode 'http' 18 | timeout connect: '5000ms', 19 | client: '5000ms', 20 | server: '5000ms' 21 | haproxy_retries 5 22 | end 23 | 24 | haproxy_listen 'admin' do 25 | bind '0.0.0.0:1337' 26 | mode 'http' 27 | stats uri: '/', 28 | realm: 'Haproxy-Statistics', 29 | auth: 'user:pwd' 30 | http_request [ 31 | 'add-header X-Forwarded-Proto https if { ssl_fc }', 32 | 'add-header X-Proto http', 33 | ] 34 | http_response 'set-header Expires %[date(3600),http_date]' 35 | default_backend 'servers' 36 | option %w(dontlog-normal) 37 | extra_options('bind-process' => 'odd') 38 | hash_type 'consistent' 39 | end 40 | 41 | haproxy_frontend 'http-in' do 42 | bind '*:80' 43 | default_backend 'servers' 44 | end 45 | 46 | haproxy_frontend 'tcp-in' do 47 | mode 'tcp' 48 | bind '*:3307' 49 | default_backend 'tcp-servers' 50 | end 51 | 52 | haproxy_frontend 'multiport' do 53 | bind '*:8080' => '', 54 | '0.0.0.0:8081' => '', 55 | '0.0.0.0:8180' => '' 56 | default_backend 'servers' 57 | end 58 | 59 | haproxy_backend 'servers' do 60 | server ['server1 127.0.0.1:8000 maxconn 32'] 61 | end 62 | 63 | haproxy_backend 'tcp-servers' do 64 | mode 'tcp' 65 | server ['server2 127.0.0.1:3306 maxconn 32'] 66 | end 67 | 68 | haproxy_service 'haproxy' do 69 | action %i(create enable start) 70 | end 71 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_acl.rb: -------------------------------------------------------------------------------- 1 | include_recipe 'test::config_2' 2 | 3 | haproxy_listen 'admin' do 4 | bind '0.0.0.0:1337' 5 | mode 'http' 6 | stats uri: '/', 7 | realm: 'Haproxy-Statistics', 8 | auth: 'user:pwd' 9 | extra_options('http-request deny if restricted_page' => '!network_allowed') 10 | end 11 | 12 | haproxy_acl 'acls for listen' do 13 | section 'listen' 14 | section_name 'admin' 15 | acl ['network_allowed src 127.0.0.1'] 16 | end 17 | 18 | haproxy_acl 'restricted_page path_beg /' do 19 | section 'listen' 20 | section_name 'admin' 21 | end 22 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_array.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'package' 4 | 5 | haproxy_config_global '' do 6 | chroot '/var/lib/haproxy' 7 | daemon true 8 | maxconn 256 9 | log '/dev/log local0' 10 | log_tag 'WARDEN' 11 | pidfile '/var/run/haproxy.pid' 12 | stats socket: '/var/lib/haproxy/stats level admin' 13 | tuning 'bufsize' => '262144' 14 | end 15 | 16 | haproxy_config_defaults 'defaults' do 17 | mode 'http' 18 | timeout connect: '5000ms', 19 | client: '5000ms', 20 | server: '5000ms' 21 | haproxy_retries 5 22 | end 23 | 24 | haproxy_frontend 'http-in' do 25 | bind '*:80' 26 | extra_options( 27 | 'redirect' => [ 28 | 'prefix http://www.bar.com code 301 if { hdr(host) -i foo.com }', 29 | 'prefix http://www.bar.com code 301 if { hdr(host) -i www.foo.com }', 30 | ] 31 | ) 32 | default_backend 'servers' 33 | end 34 | 35 | haproxy_frontend 'tcp-in' do 36 | mode 'tcp' 37 | bind '*:3307' 38 | default_backend 'tcp-servers' 39 | end 40 | 41 | bind_hash = { '*:8080' => '', '0.0.0.0:8081' => '', '0.0.0.0:8180' => '' } 42 | 43 | haproxy_frontend 'multiport' do 44 | bind bind_hash 45 | default_backend 'servers' 46 | end 47 | 48 | haproxy_backend 'servers' do 49 | server ['server1 127.0.0.1:8000 maxconn 32'] 50 | end 51 | 52 | haproxy_backend 'tcp-servers' do 53 | mode 'tcp' 54 | server ['server2 127.0.0.1:3306 maxconn 32'] 55 | end 56 | 57 | haproxy_service 'haproxy' do 58 | action %i(create enable start) 59 | end 60 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_backend_search.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'package' 4 | 5 | haproxy_config_global '' do 6 | chroot '/var/lib/haproxy' 7 | daemon true 8 | maxconn 256 9 | log '/dev/log local0' 10 | log_tag 'WARDEN' 11 | pidfile '/var/run/haproxy.pid' 12 | stats socket: '/var/lib/haproxy/stats level admin' 13 | tuning 'bufsize' => '262144' 14 | end 15 | 16 | haproxy_config_defaults 'defaults' do 17 | mode 'http' 18 | timeout connect: '5000ms', 19 | client: '5000ms', 20 | server: '5000ms' 21 | end 22 | 23 | haproxy_frontend 'http-in' do 24 | bind '*:80' 25 | default_backend 'servers' 26 | end 27 | 28 | environment = node.chef_environment 29 | role = 'app' 30 | app_backends = search(:node, "roles:#{role} AND chef_environment:#{environment}") 31 | server_array = ['disabled-server 127.0.0.1:1 disabled'] 32 | 33 | app_backends.each do |be| 34 | server_array.push("#{be['hostname']} #{be['ipaddress']}:8000 maxconn 32") 35 | end 36 | 37 | haproxy_backend 'servers' do 38 | server server_array 39 | end 40 | 41 | haproxy_service 'haproxy' do 42 | action %i(create enable start) 43 | end 44 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_custom_template.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'package' 4 | 5 | directory '/var/lib/haproxy' do 6 | owner 'haproxy' 7 | mode '0777' 8 | end 9 | 10 | haproxy_config_global '' do 11 | template 'custom-template.cfg.erb' 12 | cookbook 'test' 13 | chroot '/var/lib/haproxy' 14 | daemon true 15 | pidfile '/run/haproxy.pid' 16 | end 17 | 18 | haproxy_config_defaults '' do 19 | end 20 | 21 | haproxy_listen 'admin' do 22 | bind '0.0.0.0:1337' 23 | mode 'http' 24 | stats uri: '/', 25 | realm: 'Haproxy-Statistics', 26 | auth: 'user:pwd' 27 | end 28 | 29 | haproxy_service 'haproxy' do 30 | action %i(create enable start) 31 | end 32 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_fastcgi.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'source' 4 | 5 | haproxy_fastcgi 'php-fpm' do 6 | log_stderr 'global' 7 | docroot '/var/www/my-app' 8 | index 'index.php' 9 | option ['keep-conn'] 10 | extra_options('path-info' => '^(/.+\.php)(/.*)?$') 11 | end 12 | 13 | haproxy_frontend 'front-http' do 14 | bind('*:80' => '') 15 | mode 'http' 16 | use_backend ['back-dynamic if { path_reg ^/.+\.php(/.*)?$ }'] 17 | default_backend 'back-static' 18 | end 19 | 20 | haproxy_backend 'back-static' do 21 | mode 'http' 22 | server ['www 127.0.0.1:80'] 23 | end 24 | 25 | haproxy_backend 'back-dynamic' do 26 | mode 'http' 27 | extra_options('use-fcgi-app' => 'php-fpm') 28 | server ['php-fpm 127.0.0.1:9000 proto fcgi'] 29 | end 30 | 31 | haproxy_service 'haproxy' do 32 | action %i(create enable start) 33 | end 34 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_resolver.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'source' 4 | 5 | haproxy_config_global '' 6 | 7 | haproxy_config_defaults '' 8 | 9 | haproxy_resolver 'dns' do 10 | nameserver ['google 8.8.8.8:53'] 11 | extra_options('resolve_retries' => 30, 12 | 'timeout' => 'retry 1s') 13 | notifies :restart, 'haproxy_service[haproxy]', :delayed 14 | end 15 | 16 | haproxy_service 'haproxy' do 17 | action %i(create enable start) 18 | end 19 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/config_ssl_redirect.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'package' 4 | 5 | haproxy_config_global '' do 6 | chroot '/var/lib/haproxy' 7 | daemon true 8 | maxconn 256 9 | log '/dev/log local0' 10 | log_tag 'WARDEN' 11 | pidfile '/var/run/haproxy.pid' 12 | stats socket: '/var/lib/haproxy/stats level admin' 13 | tuning 'bufsize' => '262144' 14 | extra_options 'tune.ssl.default-dh-param' => 2048 15 | end 16 | 17 | haproxy_config_defaults 'defaults' do 18 | mode 'http' 19 | timeout connect: '5000ms', 20 | client: '5000ms', 21 | server: '5000ms' 22 | haproxy_retries 5 23 | end 24 | 25 | directory '/etc/ssl/private' do 26 | owner 'root' 27 | group 'root' 28 | mode '0755' 29 | action :create 30 | end 31 | 32 | cookbook_file '/etc/ssl/private/example.com.pem' do 33 | owner 'root' 34 | group 'root' 35 | mode '0755' 36 | action :create 37 | end 38 | 39 | haproxy_frontend 'http-in' do 40 | mode 'http' 41 | bind '*:80' 42 | extra_options redirect: 'scheme https code 301 if !{ ssl_fc }' 43 | end 44 | 45 | haproxy_frontend 'https' do 46 | mode 'http' 47 | bind '*:443 ssl crt /etc/ssl/private/example.com.pem' 48 | default_backend 'servers' 49 | end 50 | 51 | haproxy_backend 'servers' do 52 | server ['server1 127.0.0.1:8000 maxconn 32'] 53 | end 54 | 55 | haproxy_service 'haproxy' do 56 | action %i(create enable start) 57 | end 58 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/package.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | pkg_name = (platform_family?('rhel') && platform_version.to_i == 7) ? 'haproxy22' : 'haproxy' 4 | 5 | haproxy_install 'package' do 6 | package_name pkg_name 7 | enable_ius_repo true 8 | end 9 | 10 | haproxy_config_global '' 11 | 12 | haproxy_config_defaults '' 13 | 14 | haproxy_frontend 'http-in' do 15 | default_backend 'servers' 16 | end 17 | 18 | haproxy_backend 'servers' do 19 | server ['server1 127.0.0.1:8000 maxconn 32'] 20 | notifies :restart, 'haproxy_service[haproxy]', :immediately 21 | end 22 | 23 | haproxy_service 'haproxy' do 24 | action %i(create enable start) 25 | end 26 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source.rb: -------------------------------------------------------------------------------- 1 | apt_update 2 | 3 | haproxy_install 'source' 4 | 5 | haproxy_config_global '' 6 | 7 | haproxy_config_defaults '' 8 | 9 | haproxy_service 'haproxy' do 10 | action %i(create enable start) 11 | end 12 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_24.rb: -------------------------------------------------------------------------------- 1 | version = '2.4.25' 2 | 3 | haproxy_install 'source' do 4 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 5 | source_checksum '44b035bdc9ffd4935f5292c2dfd4a1596c048dc59c5b25a0c6d7689d64f50b99' 6 | source_version version 7 | use_libcrypt true 8 | use_pcre true 9 | use_openssl true 10 | use_zlib true 11 | use_promex true 12 | use_linux_tproxy true 13 | use_linux_splice true 14 | end 15 | 16 | haproxy_config_global '' 17 | 18 | haproxy_config_defaults '' 19 | 20 | haproxy_service 'haproxy' do 21 | action :create 22 | delayed_action %i(enable start) 23 | end 24 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_26.rb: -------------------------------------------------------------------------------- 1 | version = '2.6.16' 2 | 3 | haproxy_install 'source' do 4 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 5 | source_checksum 'faac6f9564caf6e106fe22c77a1fb35406afc8cd484c35c2c844aaf0d7a097fb' 6 | source_version version 7 | use_libcrypt true 8 | use_pcre true 9 | use_openssl true 10 | use_zlib true 11 | use_linux_tproxy true 12 | use_linux_splice true 13 | end 14 | 15 | haproxy_config_global '' 16 | 17 | haproxy_config_defaults '' 18 | 19 | haproxy_service 'haproxy' do 20 | action %i(create enable start) 21 | end 22 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_28.rb: -------------------------------------------------------------------------------- 1 | version = '2.8.5' 2 | 3 | haproxy_install 'source' do 4 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 5 | source_checksum '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' 6 | source_version version 7 | use_libcrypt true 8 | use_pcre true 9 | use_openssl true 10 | use_zlib true 11 | use_linux_tproxy true 12 | use_linux_splice true 13 | end 14 | 15 | haproxy_config_global '' 16 | 17 | haproxy_config_defaults '' 18 | 19 | haproxy_service 'haproxy' do 20 | action :create 21 | delayed_action %i(enable start) 22 | end 23 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_29.rb: -------------------------------------------------------------------------------- 1 | version = '2.9.3' 2 | 3 | haproxy_install 'source' do 4 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 5 | source_checksum 'ed517c65abd86945411f6bcb18c7ec657a706931cb781ea283063ba0a75858c0' 6 | source_version version 7 | use_libcrypt true 8 | use_pcre true 9 | use_openssl true 10 | use_zlib true 11 | use_linux_tproxy true 12 | use_linux_splice true 13 | end 14 | 15 | haproxy_config_global '' 16 | 17 | haproxy_config_defaults '' 18 | 19 | haproxy_service 'haproxy' do 20 | action :create 21 | delayed_action %i(enable start) 22 | end 23 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_lua.rb: -------------------------------------------------------------------------------- 1 | build_essential 'compilation tools' 2 | 3 | # install lua dependencies 4 | case node['platform_family'] 5 | when 'rhel', 'fedora' 6 | package %w( 7 | readline-devel 8 | ncurses-devel 9 | pcre-devel 10 | openssl-devel 11 | zlib-devel 12 | ) 13 | when 'debian' 14 | package %w( 15 | libreadline-dev 16 | libncurses5-dev 17 | libpcre3-dev 18 | libssl-dev 19 | zlib1g-dev 20 | liblua5.3-dev 21 | ) 22 | end 23 | 24 | # download lua 25 | remote_file "#{Chef::Config[:file_cache_path]}/lua-5.3.1.tar.gz" do 26 | source 'http://lua.org/ftp/lua-5.3.1.tar.gz' 27 | owner 'root' 28 | group 'root' 29 | mode '0755' 30 | action :create 31 | not_if { ::File.exist?('/opt/lua-5.3.1/bin/lua') } 32 | end 33 | 34 | # extract lua 35 | execute 'lua extract' do 36 | command 'tar xf lua-5.3.1.tar.gz' 37 | cwd "#{Chef::Config[:file_cache_path]}" 38 | not_if { ::File.exist?('/opt/lua-5.3.1/bin/lua') } 39 | end 40 | 41 | # compile lua 42 | execute 'lua compile' do 43 | command 'make linux' 44 | cwd "#{Chef::Config[:file_cache_path]}/lua-5.3.1" 45 | not_if { ::File.exist?('/opt/lua-5.3.1/bin/lua') } 46 | end 47 | 48 | execute 'lua install' do 49 | command 'make INSTALL_TOP=/opt/lua-5.3.1 install' 50 | cwd "#{Chef::Config[:file_cache_path]}/lua-5.3.1" 51 | not_if { ::File.exist?('/opt/lua-5.3.1/bin/lua') } 52 | end 53 | 54 | version = '2.4.25' 55 | 56 | haproxy_install 'source' do 57 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 58 | source_checksum '44b035bdc9ffd4935f5292c2dfd4a1596c048dc59c5b25a0c6d7689d64f50b99' 59 | source_version version 60 | use_pcre true 61 | use_openssl true 62 | use_zlib true 63 | use_linux_tproxy true 64 | use_linux_splice true 65 | use_lua true 66 | lua_lib '/opt/lua-5.3.1/lib' 67 | lua_inc '/opt/lua-5.3.1/include' 68 | end 69 | 70 | haproxy_config_global '' 71 | 72 | haproxy_config_defaults '' 73 | 74 | haproxy_service 'haproxy' do 75 | action :create 76 | delayed_action %i(enable start) 77 | end 78 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_openssl.rb: -------------------------------------------------------------------------------- 1 | build_essential 'compilation tools' 2 | 3 | # package %w(build-essential zlib1g-dev) if platform_family?('debian') 4 | 5 | # package %w(make gcc perl pcre-devel zlib-devel perl-core) if platform_family?('rhel') 6 | 7 | # override environment variable 8 | ruby_block 'Pre-load OpenSSL path' do 9 | block do 10 | ENV['PATH'] = "/usr/local/openssl/bin:#{ENV['PATH']}" 11 | end 12 | end 13 | 14 | openssl_version = '3.2.1' 15 | 16 | # download openssl 17 | remote_file "#{Chef::Config[:file_cache_path]}/openssl-#{openssl_version}.tar.gz" do 18 | source "https://www.openssl.org/source/openssl-#{openssl_version}.tar.gz" 19 | checksum '83c7329fe52c850677d75e5d0b0ca245309b97e8ecbcfdc1dfdc4ab9fac35b39' 20 | end 21 | 22 | # extract openssl 23 | execute "extract_openssl-#{openssl_version}.tar.gz" do 24 | command "tar -zxf #{Chef::Config[:file_cache_path]}/openssl-#{openssl_version}.tar.gz -C /tmp" 25 | not_if { ::File.exist?("/tmp/openssl-#{openssl_version}/") } 26 | end 27 | 28 | # compile openssl 29 | execute "package_openssl-#{openssl_version}" do 30 | command <<-COMPILE 31 | ./config --prefix=/usr/local/openssl/ --openssldir=/usr/local/openssl/ shared zlib 32 | make 33 | make install 34 | COMPILE 35 | cwd "/tmp/openssl-#{openssl_version}" 36 | not_if { ::File.exist?('/usr/local/openssl/') } 37 | end 38 | 39 | # create symlinks 40 | if rhel? 41 | # Shared libraries 42 | file "/etc/ld.so.conf.d/openssl-#{openssl_version}.conf" do 43 | content '/usr/local/openssl/lib' 44 | notifies :run, 'execute[reload ldconfig]' 45 | end 46 | 47 | execute 'reload ldconfig' do 48 | command 'ldconfig -v' 49 | action :nothing 50 | end 51 | end 52 | 53 | # install haproxy with openssl 54 | version = '2.9.3' 55 | 56 | haproxy_install 'source' do 57 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 58 | source_checksum 'ed517c65abd86945411f6bcb18c7ec657a706931cb781ea283063ba0a75858c0' 59 | source_version version 60 | use_openssl true 61 | use_zlib true 62 | use_linux_tproxy true 63 | use_linux_splice true 64 | use_systemd true 65 | ssl_lib '/usr/local/openssl/lib' 66 | ssl_inc '/usr/local/openssl/include' 67 | end 68 | -------------------------------------------------------------------------------- /test/cookbooks/test/templates/default/custom-template.cfg.erb: -------------------------------------------------------------------------------- 1 | # testsuite needs user/group/pidfile/chroot/daemon to be set! 2 | <% unless @global.nil? %> 3 | global 4 | user <%= @global['user'] %> 5 | group <%= @global['group'] %> 6 | <% if @global['pid_file'] -%> 7 | pidfile <%= @global['pid_file'] %> 8 | <% end %> 9 | <% if @global['log'] && @global['log'].is_a?(Array)-%> 10 | <% @global['log'].each do | logvar | -%> 11 | <% if logvar && logvar.is_a?(Array)-%> 12 | <% logvar.each do | log | -%> 13 | log <%= log %> 14 | <% end -%> 15 | <% else -%> 16 | log <%= logvar %> 17 | <% end -%> 18 | <% end -%> 19 | <% end -%> 20 | <% if @global['log_tag'] -%> 21 | log-tag <%= @global['log_tag'] %> 22 | <% end -%> 23 | <% if @global['chroot'] -%> 24 | chroot <%= @global['chroot'] %> 25 | <% end -%> 26 | <% if @global['daemon'].eql? 'true' -%> 27 | daemon 28 | <% end -%> 29 | <%= @global['debug_option'] %> 30 | <% @global['stats'].each do |option, value| -%> 31 | stats <%= option %> <%= value %> 32 | <% end -%> 33 | <% unless @global['maxconn'].nil? -%> 34 | maxconn <%= @global['maxconn'] %> 35 | <% end -%> 36 | <% if @global['pidfile'] -%> 37 | pidfile <%= @global['pidfile'] %> 38 | <% end -%> 39 | <% unless @global['tuning'].nil? %> 40 | <% @global['tuning'].each do | option, value | -%> 41 | tune.<%= option %> <%= value %> 42 | <% end -%> 43 | <% end -%> 44 | <% unless @global['extra_options'].nil? -%> 45 | <% @global['extra_options'].each do | option, value | -%> 46 | <%= option %> <%= value %> 47 | <% end -%> 48 | <% end -%> 49 | <% end -%> 50 | 51 | # Omission of frontends/listen/backend is deliberate 52 | -------------------------------------------------------------------------------- /test/integration/common/controls/common_spec.rb: -------------------------------------------------------------------------------- 1 | describe directory '/etc/haproxy' do 2 | it { should exist } 3 | end 4 | 5 | describe file('/etc/haproxy/haproxy.cfg') do 6 | it { should exist } 7 | it { should be_owned_by 'haproxy' } 8 | it { should be_grouped_into 'haproxy' } 9 | end 10 | 11 | describe service('haproxy') do 12 | it { should be_running } 13 | end 14 | -------------------------------------------------------------------------------- /test/integration/common/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-common 3 | title: HAProxy Common Suite 4 | summary: HAProxy common tests 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | -------------------------------------------------------------------------------- /test/integration/config_2/controls/config_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | describe package('haproxy') do 4 | it { should be_installed } 5 | end 6 | 7 | # cfg_content = [ 8 | # 'global', 9 | # ' user haproxy', 10 | # ' group haproxy', 11 | # ' log /dev/log syslog info', 12 | # ' log-tag haproxy', 13 | # ' chroot /var/lib/haproxy', 14 | # ' quiet', 15 | # ' stats socket /var/lib/haproxy/haproxy\.stat mode 600 level admin', 16 | # ' stats timeout 2m', 17 | # ' maxconn 4097', 18 | # ' pidfile /var/run/haproxy\.pid', 19 | # '', 20 | # '', 21 | # 'defaults', 22 | # ' timeout connect 5s', 23 | # ' timeout client 50s', 24 | # ' timeout server 50s', 25 | # ' log global', 26 | # ' mode http', 27 | # ' balance roundrobin', 28 | # ' option dontlognull', 29 | # ' option redispatch', 30 | # ' option tcplog', 31 | # '', 32 | # '', 33 | # 'frontend http', 34 | # ' default_backend rrhost', 35 | # ' bind 0\.0\.0\.0:80', 36 | # ' maxconn 2000', 37 | # ' stats uri /haproxy\?stats', 38 | # ' acl kml_request path_reg -i /kml/', 39 | # ' acl bbox_request path_reg -i /bbox/', 40 | # ' acl gina_host hdr\(host\) -i foo\.bar\.com', 41 | # ' acl rrhost_host hdr\(host\) -i dave\.foo\.bar\.com foo\.foo\.com', 42 | # ' acl source_is_abuser src_get_gpc0\(http\) gt 0', 43 | # ' acl tile_host hdr\(host\) -i dough\.foo\.bar\.com', 44 | # ' use_backend gina if gina_host', 45 | # ' use_backend rrhost if rrhost_host', 46 | # ' use_backend abuser if source_is_abuser', 47 | # ' use_backend tiles_public if tile_host', 48 | # ' option dontlognull', 49 | # ' option forwardfor', 50 | # ' stick-table type ip size 200k expire 10m store gpc0', 51 | # ' tcp-request connection track-sc1 src if !source_is_abuser', 52 | # '', 53 | # '', 54 | # 'backend tiles_public', 55 | # ' server tile0 10\.0\.0\.10:80 check weight 1 maxconn 100', 56 | # ' server tile1 10\.0\.0\.10:80 check weight 1 maxconn 100', 57 | # ' acl conn_rate_abuse sc2_conn_rate gt 3000', 58 | # ' acl data_rate_abuse sc2_bytes_out_rate gt 20000000', 59 | # ' acl mark_as_abuser sc1_inc_gpc0 gt 0', 60 | # ' option httplog', 61 | # ' option dontlognull', 62 | # ' option forwardfor', 63 | # ' tcp-request content track-sc2 src', 64 | # ' tcp-request content reject if conn_rate_abuse mark_as_abuser', 65 | # ' stick-table type ip size 200k expire 2m store conn_rate\(60s\),bytes_out_rate\(60s\)', 66 | # ' http-request set-header X-Public-User yes', 67 | # '', 68 | # '', 69 | # 'backend abuser', 70 | # ' errorfile 403 /etc/haproxy/errors/403\.http', 71 | # '', 72 | # '', 73 | # 'backend rrhost', 74 | # ' server tile0 10\.0\.0\.10:80 check weight 1 maxconn 100', 75 | # ' server tile1 10\.0\.0\.10:80 check weight 1 maxconn 100', 76 | # '', 77 | # '', 78 | # 'backend gina', 79 | # ' server tile0 10\.0\.0\.10:80 check weight 1 maxconn 100', 80 | # ' server tile1 10\.0\.0\.10:80 check weight 1 maxconn 100', 81 | # ] 82 | 83 | # describe file('/etc/haproxy/haproxy.cfg') do 84 | # its('content') { should match(/#{cfg_content.join('\n')}/) } 85 | # end 86 | -------------------------------------------------------------------------------- /test/integration/config_2/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-2 3 | title: HAProxy Config 2 Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_3/controls/config_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | describe package('haproxy') do 4 | it { should be_installed } 5 | end 6 | 7 | cfg_content = [ 8 | 'global', 9 | ' user haproxy', 10 | ' group haproxy', 11 | ' log /dev/log local0', 12 | ' log /dev/log local1 notice', 13 | ' log-tag WARDEN', 14 | ' chroot /var/lib/haproxy', 15 | ' daemon', 16 | ' quiet', 17 | ' stats socket /var/lib/haproxy/stats level admin', 18 | ' maxconn 256', 19 | ' pidfile /var/run/haproxy\.pid', 20 | ' tune\.bufsize 262144', 21 | '', 22 | '', 23 | 'defaults', 24 | ' timeout connect 5000ms', 25 | ' timeout client 5000ms', 26 | ' timeout server 5000ms', 27 | ' log global', 28 | ' mode http', 29 | ' balance roundrobin', 30 | ' option httplog', 31 | ' option dontlognull', 32 | ' option redispatch', 33 | ' option tcplog', 34 | ' retries 5', 35 | '', 36 | '', 37 | 'frontend http-in', 38 | ' default_backend servers', 39 | ' bind \*:80', 40 | '', 41 | '', 42 | 'frontend tcp-in', 43 | ' mode tcp', 44 | ' default_backend tcp-servers', 45 | ' bind \*:3307', 46 | '', 47 | '', 48 | 'frontend multiport', 49 | ' default_backend servers', 50 | ' bind \*:8080', 51 | ' bind 0\.0\.0\.0:8081', 52 | ' bind 0\.0\.0\.0:8180', 53 | '', 54 | '', 55 | 'backend servers', 56 | ' server server1 127\.0\.0\.1:8000 maxconn 32', 57 | '', 58 | '', 59 | 'backend tcp-servers', 60 | ' mode tcp', 61 | ' server server2 127\.0\.0\.1:3306 maxconn 32', 62 | '', 63 | '', 64 | 'listen admin', 65 | ' mode http', 66 | ' bind 0.0.0.0:1337', 67 | ' stats uri /', 68 | ' stats realm Haproxy-Statistics', 69 | ' stats auth user:pwd', 70 | ' http-request add-header X-Forwarded-Proto https if { ssl_fc }', 71 | ' http-request add-header X-Proto http', 72 | ' http-response set-header Expires %\[date\(3600\),http_date\]', 73 | ' default_backend servers', 74 | ' option dontlog-normal', 75 | ' bind-process odd', 76 | ' hash-type consistent', 77 | ] 78 | 79 | describe file('/etc/haproxy/haproxy.cfg') do 80 | its('content') { should match(/#{cfg_content.join('\n')}/) } 81 | end 82 | -------------------------------------------------------------------------------- /test/integration/config_3/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-3 3 | title: HAProxy Config 3 Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_acl/controls/config_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | describe package('haproxy') do 4 | it { should be_installed } 5 | end 6 | 7 | describe file('/etc/haproxy/haproxy.cfg') do 8 | its('content') { should_not match(/^ daemon$/) } 9 | # Defaults 10 | defaults = [ 11 | 'defaults', 12 | ' timeout connect 5s', 13 | ' timeout client 50s', 14 | ' timeout server 50s', 15 | ' log global', 16 | ' mode http', 17 | ' balance roundrobin', 18 | ' option httplog', 19 | ' option dontlognull', 20 | ' option redispatch', 21 | ' option tcplog', 22 | ] 23 | its('content') { should match(/#{defaults.join('\n')}/) } 24 | 25 | # Frontend http 26 | # frontend_http = [ 27 | # 'frontend http', 28 | # ' default_backend rrhost', 29 | # ' bind 0.0.0.0:80', 30 | # ' maxconn 2000', 31 | # ' acl kml_request path_reg -i /kml/', 32 | # ' acl bbox_request path_reg -i /bbox/', 33 | # ' acl source_is_abuser src_get_gpc0\(http\) gt 0', 34 | # ' acl gina_host hdr\(host\) -i foo.bar.com', 35 | # ' acl rrhost_host hdr\(host\) -i dave.foo.bar.com foo.foo.com', 36 | # ' acl tile_host hdr\(host\) -i dough.foo.bar.com', 37 | # ' use_backend abuser if source_is_abuser', 38 | # ' use_backend gina if gina_host', 39 | # ' use_backend rrhost if rrhost_host', 40 | # ' use_backend tiles_public if tile_host', 41 | # ' option httplog', 42 | # ' option dontlognull', 43 | # ' option forwardfor', 44 | # ' stick-table type ip size 200k expire 10m store gpc0', 45 | # ' tcp-request connection track-sc1 src if !source_is_abuser', 46 | # ] 47 | # its('content') { should match(/#{frontend_http.join('\n')}/) } 48 | 49 | # Backend tiles_public 50 | # tiles_public = [ 51 | # 'backend tiles_public', 52 | # ' server tile0 10.0.0.10:80 check weight 1 maxconn 100', 53 | # ' server tile1 10.0.0.10:80 check weight 1 maxconn 100', 54 | # ' acl conn_rate_abuse sc2_conn_rate gt 3000', 55 | # ' acl data_rate_abuse sc2_bytes_out_rate gt 20000000', 56 | # ' acl mark_as_abuser sc1_inc_gpc0 gt 0', 57 | # ' tcp-request content track-sc2 src', 58 | # ' tcp-request content reject if conn_rate_abuse mark_as_abuser', 59 | # ' stick-table type ip size 200k expire 2m store conn_rate\(60s\),bytes_out_rate\(60s\)', 60 | # ' http-request set-header X-Public-User yes', 61 | # ] 62 | # its('content') { should match(/#{tiles_public.join('\n')}/) } 63 | 64 | # Listen admin 65 | listen_admin = [ 66 | 'listen admin', 67 | ' mode http', 68 | ' bind 0.0.0.0:1337', 69 | ' stats uri /', 70 | ' stats realm Haproxy-Statistics', 71 | ' stats auth user:pwd', 72 | ' acl network_allowed src 127.0.0.1', 73 | ' acl restricted_page path_beg /', 74 | ' http-request deny if restricted_page !network_allowed', 75 | ] 76 | its('content') { should match(/#{listen_admin.join('\n')}/) } 77 | end 78 | -------------------------------------------------------------------------------- /test/integration/config_acl/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-acl 3 | title: HAProxy Config ACL Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_array/controls/config_spec.rb: -------------------------------------------------------------------------------- 1 | title 'Frontend & Backend should be configurable' 2 | 3 | include_controls 'haproxy-common' 4 | 5 | describe package('haproxy') do 6 | it { should be_installed } 7 | end 8 | 9 | cfg_content = [ 10 | 'global', 11 | ' user haproxy', 12 | ' group haproxy', 13 | ' log /dev/log local0', 14 | ' log-tag WARDEN', 15 | ' chroot /var/lib/haproxy', 16 | ' daemon', 17 | ' quiet', 18 | ' stats socket /var/lib/haproxy/stats level admin', 19 | ' maxconn 256', 20 | ' pidfile /var/run/haproxy\.pid', 21 | ' tune\.bufsize 262144', 22 | '', 23 | '', 24 | 'defaults', 25 | ' timeout connect 5000ms', 26 | ' timeout client 5000ms', 27 | ' timeout server 5000ms', 28 | ' log global', 29 | ' mode http', 30 | ' balance roundrobin', 31 | ' option httplog', 32 | ' option dontlognull', 33 | ' option redispatch', 34 | ' option tcplog', 35 | ' retries 5', 36 | '', 37 | '', 38 | 'frontend http-in', 39 | ' default_backend servers', 40 | ' bind \*:80', 41 | ' redirect prefix http://www\.bar\.com code 301 if \{ hdr\(host\) -i foo\.com \}', 42 | ' redirect prefix http://www\.bar\.com code 301 if \{ hdr\(host\) -i www\.foo\.com \}', 43 | '', 44 | '', 45 | 'frontend tcp-in', 46 | ' mode tcp', 47 | ' default_backend tcp-servers', 48 | ' bind \*:3307', 49 | '', 50 | '', 51 | 'frontend multiport', 52 | ' default_backend servers', 53 | ' bind \*:8080', 54 | ' bind 0\.0\.0\.0:8081', 55 | ' bind 0\.0\.0\.0:8180', 56 | '', 57 | '', 58 | 'backend servers', 59 | ' server server1 127\.0\.0\.1:8000 maxconn 32', 60 | '', 61 | '', 62 | 'backend tcp-servers', 63 | ' mode tcp', 64 | ' server server2 127\.0\.0\.1:3306 maxconn 32', 65 | ] 66 | 67 | describe file('/etc/haproxy/haproxy.cfg') do 68 | its('content') { should match(/#{cfg_content.join('\n')}/) } 69 | end 70 | -------------------------------------------------------------------------------- /test/integration/config_array/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-array 3 | title: HAProxy Config Array Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_backend_search/controls/config_backend_search_spec.rb: -------------------------------------------------------------------------------- 1 | title 'Frontend & Backend should be configurable' 2 | 3 | include_controls 'haproxy-common' 4 | 5 | describe package('haproxy') do 6 | it { should be_installed } 7 | end 8 | 9 | cfg_content = [ 10 | 'global', 11 | ' user haproxy', 12 | ' group haproxy', 13 | ' log /dev/log local0', 14 | ' log-tag WARDEN', 15 | ' chroot /var/lib/haproxy', 16 | ' daemon', 17 | ' quiet', 18 | ' stats socket /var/lib/haproxy/stats level admin', 19 | ' maxconn 256', 20 | ' pidfile /var/run/haproxy\.pid', 21 | ' tune\.bufsize 262144', 22 | '', 23 | '', 24 | 'defaults', 25 | ' timeout connect 5000ms', 26 | ' timeout client 5000ms', 27 | ' timeout server 5000ms', 28 | ' log global', 29 | ' mode http', 30 | ' balance roundrobin', 31 | ' option httplog', 32 | ' option dontlognull', 33 | ' option redispatch', 34 | ' option tcplog', 35 | '', 36 | '', 37 | 'frontend http-in', 38 | ' default_backend servers', 39 | ' bind \*:80', 40 | '', 41 | '', 42 | 'backend servers', 43 | ' server disabled-server 127\.0\.0\.1:1 disabled', 44 | ' server be-1 10\.0\.0\.75:8000 maxconn 32', 45 | ' server be-2 10\.0\.0\.76:8000 maxconn 32', 46 | ] 47 | 48 | describe file('/etc/haproxy/haproxy.cfg') do 49 | its('content') { should match(/#{cfg_content.join('\n')}/) } 50 | end 51 | -------------------------------------------------------------------------------- /test/integration/config_backend_search/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-backend-search 3 | title: HAProxy Config Backend Search Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_custom_template/controls/template_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | cfg_content = [ 4 | 'global', 5 | ' user haproxy', 6 | ' group haproxy', 7 | ' log /dev/log syslog info', 8 | ' log-tag haproxy', 9 | ' chroot /var/lib/haproxy', 10 | ' daemon', 11 | ' quiet', 12 | ' stats socket /var/run/haproxy\.sock user haproxy group haproxy', 13 | ' stats timeout 2m', 14 | ' maxconn 4096', 15 | ' pidfile /run/haproxy\.pid', 16 | ] 17 | 18 | describe file('/etc/haproxy/haproxy.cfg') do 19 | its('content') { should match(/#{cfg_content.join('\n')}/) } 20 | end 21 | -------------------------------------------------------------------------------- /test/integration/config_custom_template/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-custom-template 3 | title: HAProxy Config Custom Template Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_fastcgi/controls/fast_cgi_spec.rb: -------------------------------------------------------------------------------- 1 | title 'FastCGI should be configurable' 2 | 3 | include_controls 'haproxy-common' 4 | 5 | cfg_content = [ 6 | 'fcgi-app php-fpm', 7 | ' docroot /var/www/my-app', 8 | ' index index.php', 9 | ' log-stderr global', 10 | ' option keep-conn', 11 | ' path-info \^\(\/\.\+\\\.php\)\(\/\.\*\)\?\$', 12 | '', 13 | '', 14 | 'frontend front-http', 15 | ' mode http', 16 | ' default_backend back-static', 17 | ' bind \*:80', 18 | ' use_backend back-dynamic if \{ path_reg \^\/\.\+\\\.php\(\/\.\*\)\?\$ \}', 19 | '', 20 | '', 21 | 'backend back-static', 22 | ' mode http', 23 | ' server www 127.0.0.1:80', 24 | '', 25 | '', 26 | 'backend back-dynamic', 27 | ' mode http', 28 | ' server php-fpm 127.0.0.1:9000 proto fcgi', 29 | ' use-fcgi-app php-fpm', 30 | ] 31 | 32 | describe file('/etc/haproxy/haproxy.cfg') do 33 | its('content') { should match(/#{cfg_content.join('\n')}/) } 34 | end 35 | -------------------------------------------------------------------------------- /test/integration/config_fastcgi/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-fast-csgi 3 | title: HAProxy Config FastCGI Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_resolver/controls/resolver_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | cfg_content = [ 4 | 'global', 5 | ' user haproxy', 6 | ' group haproxy', 7 | ' log /dev/log syslog info', 8 | ' log-tag haproxy', 9 | ' daemon', 10 | ' quiet', 11 | ' stats socket /var/run/haproxy\.sock user haproxy group haproxy', 12 | ' stats timeout 2m', 13 | ' maxconn 4096', 14 | ' pidfile /var/run/haproxy\.pid', 15 | '', 16 | '', 17 | 'resolvers dns', 18 | ' nameserver google 8\.8\.8\.8:53', 19 | ' resolve_retries 30', 20 | ' timeout retry 1s', 21 | '', 22 | '', 23 | 'defaults', 24 | ' timeout client 10s', 25 | ' timeout server 10s', 26 | ' timeout connect 10s', 27 | ' log global', 28 | ' mode http', 29 | ' balance roundrobin', 30 | ' option httplog', 31 | ' option dontlognull', 32 | ' option redispatch', 33 | ' option tcplog', 34 | ] 35 | 36 | describe file('/etc/haproxy/haproxy.cfg') do 37 | its('content') { should match(/#{cfg_content.join('\n')}/) } 38 | end 39 | -------------------------------------------------------------------------------- /test/integration/config_resolver/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-resolver 3 | title: HAProxy Config Resolver Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/config_ssl_redirect/controls/ssl_redirect_spec.rb: -------------------------------------------------------------------------------- 1 | title 'Frontend & Backend should be configurable' 2 | 3 | include_controls 'haproxy-common' 4 | 5 | cfg_content = [ 6 | 'global', 7 | ' user haproxy', 8 | ' group haproxy', 9 | ' log /dev/log local0', 10 | ' log-tag WARDEN', 11 | ' chroot /var/lib/haproxy', 12 | ' daemon', 13 | ' quiet', 14 | ' stats socket /var/lib/haproxy/stats level admin', 15 | ' maxconn 256', 16 | ' pidfile /var/run/haproxy\.pid', 17 | ' tune\.bufsize 262144', 18 | ' tune\.ssl\.default-dh-param 2048', 19 | '', 20 | '', 21 | 'defaults', 22 | ' timeout connect 5000ms', 23 | ' timeout client 5000ms', 24 | ' timeout server 5000ms', 25 | ' log global', 26 | ' mode http', 27 | ' balance roundrobin', 28 | ' option httplog', 29 | ' option dontlognull', 30 | ' option redispatch', 31 | ' option tcplog', 32 | ' retries 5', 33 | '', 34 | '', 35 | 'frontend http-in', 36 | ' mode http', 37 | ' bind \*:80', 38 | ' redirect scheme https code 301 if !\{ ssl_fc \}', 39 | '', 40 | '', 41 | 'frontend https', 42 | ' mode http', 43 | ' default_backend servers', 44 | ' bind \*:443 ssl crt /etc/ssl/private/example\.com\.pem', 45 | '', 46 | '', 47 | 'backend servers', 48 | ' server server1 127\.0\.0\.1:8000 maxconn 32', 49 | ] 50 | 51 | describe file('/etc/haproxy/haproxy.cfg') do 52 | its('content') { should match(/#{cfg_content.join('\n')}/) } 53 | end 54 | -------------------------------------------------------------------------------- /test/integration/config_ssl_redirect/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-config-ssl-redirect 3 | title: HAProxy Config SSL Redirect Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/nodes/be-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "be-1", 3 | "run_list": ["role[app]"], 4 | "automatic": { 5 | "hostname": "be-1", 6 | "ipaddress": "10.0.0.75", 7 | "roles": ["app"] 8 | } 9 | } -------------------------------------------------------------------------------- /test/integration/nodes/be-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "be-2", 3 | "run_list": ["role[app]"], 4 | "automatic": { 5 | "hostname": "be-2", 6 | "ipaddress": "10.0.0.76", 7 | "roles": ["app"] 8 | } 9 | } -------------------------------------------------------------------------------- /test/integration/package/controls/package_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | -------------------------------------------------------------------------------- /test/integration/package/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-package 3 | title: HAProxy Package Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source-default/controls/source_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | -------------------------------------------------------------------------------- /test/integration/source-default/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-source-default 3 | title: HAProxy Source Default 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source_2.4/controls/source_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | describe command('haproxy -vv') do 4 | its('stdout') { should match(/Built with the Prometheus exporter as a service/) } 5 | end 6 | -------------------------------------------------------------------------------- /test/integration/source_2.4/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-source-2.4 3 | title: HAProxy Source Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source_2.6/controls/source_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | -------------------------------------------------------------------------------- /test/integration/source_2.6/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-source-2.6 3 | title: HAProxy Source Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source_2.8/controls/source_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | -------------------------------------------------------------------------------- /test/integration/source_2.8/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-source-2.8 3 | title: HAProxy Source Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source_2.9/controls/source_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | -------------------------------------------------------------------------------- /test/integration/source_2.9/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-source-2.9 3 | title: HAProxy Source Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source_lua/controls/lua_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | describe directory '/opt/lua-5.3.1' do 4 | it { should exist } 5 | end 6 | 7 | describe command('haproxy -vv | grep Lua') do 8 | its('stdout') { should match(/Built with Lua version/) } 9 | end 10 | -------------------------------------------------------------------------------- /test/integration/source_lua/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-source-lua 3 | title: HAProxy Source Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | -------------------------------------------------------------------------------- /test/integration/source_openssl/controls/openssl_spec.rb: -------------------------------------------------------------------------------- 1 | include_controls 'haproxy-common' 2 | 3 | describe file '/usr/bin/openssl' do 4 | it { should exist } 5 | end 6 | 7 | describe directory '/usr/local/openssl/bin/' do 8 | it { should exist } 9 | end 10 | 11 | describe command('haproxy -vv') do 12 | its('stdout') { should match(/OpenSSL version : OpenSSL 3.2.1/) } 13 | end 14 | -------------------------------------------------------------------------------- /test/integration/source_openssl/inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: haproxy-open-ssl 3 | title: HAProxy OpenSSL Suite 4 | summary: HAProxy tests using example configuration 5 | supports: 6 | - os-family: linux 7 | - os-family: bsd 8 | depends: 9 | - name: haproxy-common 10 | path: test/integration/common 11 | --------------------------------------------------------------------------------