├── .editorconfig ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS ├── copilot-instructions.md ├── lock.yml └── workflows │ ├── ci.yml │ ├── conventional-commits.yml │ ├── copilot-setup-steps.yml │ ├── prevent-file-change.yml │ ├── release.yml │ └── stale.yml ├── .gitignore ├── .markdownlint-cli2.yaml ├── .markdownlint.json ├── .mdlrc ├── .overcommit.yml ├── .release-please-manifest.json ├── .rubocop.yml ├── .vscode └── extensions.json ├── .windsurf └── rules │ └── definition-of-done.md ├── .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 ├── mise.toml ├── release-please-config.json ├── 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_28_pcre2.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 └── version.rb /.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/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | # HAProxy Cookbook Development Instructions 2 | 3 | **ALWAYS follow these instructions first and fallback to additional search and context gathering only if the information here is incomplete or found to be in error.** 4 | 5 | This is a Chef cookbook for installing and configuring HAProxy load balancer. It provides custom Chef resources for managing HAProxy installations, configurations, and services across multiple platforms. 6 | 7 | ## Working Effectively 8 | 9 | ### Bootstrap Environment and Dependencies 10 | ```bash 11 | # Install Chef development tools (choose one method): 12 | # Method 1: Install Chef Workstation (recommended) 13 | wget https://packages.chef.io/files/stable/chef-workstation/24.12.1031/ubuntu/24.04/chef-workstation_24.12.1031-1_amd64.deb 14 | sudo dpkg -i chef-workstation_24.12.1031-1_amd64.deb 15 | 16 | # Method 2: Install individual gems if Chef Workstation fails 17 | sudo gem install cookstyle chefspec rspec berkshelf test-kitchen kitchen-dokken --no-document 18 | ``` 19 | 20 | ### Core Development Commands 21 | ```bash 22 | # Install cookbook dependencies (if berkshelf is available) 23 | berks install 24 | # NOTE: If berkshelf is not installed, cookbook will still work for basic linting/testing 25 | 26 | # Lint Ruby code - takes 2-3 seconds - NEVER CANCEL 27 | cookstyle . 28 | 29 | # Fix auto-correctable linting issues 30 | cookstyle -a . 31 | 32 | # Run unit tests - takes 30 seconds to 2 minutes - NEVER CANCEL 33 | # NOTE: Requires full Chef installation with chefspec gem 34 | rspec spec/ 35 | 36 | # Run all unit tests with detailed output 37 | rspec spec/ --format documentation 38 | ``` 39 | 40 | ### Integration Testing (Advanced) 41 | **CRITICAL**: Integration tests require Docker and take 15-45 minutes per suite. NEVER CANCEL. 42 | **NOTE**: Requires test-kitchen and kitchen-dokken gems installed. 43 | 44 | ```bash 45 | # List all available test suites (requires test-kitchen installation) 46 | kitchen list 47 | 48 | # Test a specific suite - NEVER CANCEL: Takes 15-45 minutes 49 | # Set timeout to 60+ minutes for any kitchen commands 50 | kitchen test package-ubuntu-2204 51 | 52 | # Test source compilation (takes longest) - NEVER CANCEL: Takes 30-60 minutes 53 | kitchen test source-default-ubuntu-2204 54 | 55 | # Destroy test instances after testing 56 | kitchen destroy 57 | ``` 58 | 59 | ### Build Validation Workflow 60 | **Minimal validation** (works in any environment with cookstyle): 61 | ```bash 62 | # 1. Lint code (~2-3 seconds) - ALWAYS WORKS 63 | cookstyle . 64 | 65 | # 2. Fix linting issues automatically - ALWAYS WORKS 66 | cookstyle -a . 67 | 68 | # 3. Verify Ruby syntax - ALWAYS WORKS 69 | ruby -c resources/install.rb 70 | ruby -c resources/service.rb 71 | ``` 72 | 73 | **Full validation** (requires complete Chef environment): 74 | ```bash 75 | # 1. Lint code (~2-3 seconds) 76 | cookstyle . 77 | 78 | # 2. Run unit tests (~30 seconds - 2 minutes) - NEVER CANCEL 79 | rspec spec/ 80 | 81 | # 3. Test basic package installation (15-30 minutes) - NEVER CANCEL 82 | kitchen test package-ubuntu-2204 83 | 84 | # 4. Clean up test instances 85 | kitchen destroy 86 | ``` 87 | 88 | ## Timing Expectations and Timeouts 89 | - **Linting (`cookstyle`)**: 2-3 seconds 90 | - **Unit tests (`rspec`)**: 30 seconds to 2 minutes - NEVER CANCEL 91 | - **Single integration test**: 15-45 minutes - NEVER CANCEL - Set timeout to 60+ minutes 92 | - **Source compilation tests**: 30-60 minutes - NEVER CANCEL - Set timeout to 90+ minutes 93 | - **Full CI matrix**: 1-2 hours across all platforms and suites 94 | 95 | **CRITICAL**: Always set timeouts of 60+ minutes for kitchen commands and 30+ minutes for unit tests. 96 | 97 | ## Manual Validation Scenarios 98 | 99 | After making changes, ALWAYS test at least one complete scenario: 100 | 101 | ### Package Installation Validation 102 | ```bash 103 | # Test the most common installation method 104 | kitchen converge package-ubuntu-2204 105 | kitchen verify package-ubuntu-2204 106 | kitchen destroy package-ubuntu-2204 107 | ``` 108 | 109 | ### Source Compilation Validation 110 | ```bash 111 | # Test source compilation (most complex scenario) 112 | kitchen converge source-default-ubuntu-2204 113 | kitchen verify source-default-ubuntu-2204 114 | kitchen destroy source-default-ubuntu-2204 115 | ``` 116 | 117 | ### Configuration Validation 118 | ```bash 119 | # Test configuration management 120 | kitchen converge config-2-ubuntu-2204 121 | kitchen verify config-2-ubuntu-2204 122 | kitchen destroy config-2-ubuntu-2204 123 | ``` 124 | 125 | ## Repository Structure and Navigation 126 | 127 | ### Key Directories 128 | - `resources/` - Custom Chef resources (install.rb, service.rb, config_global.rb, etc.) 129 | - `libraries/` - Helper modules and shared code 130 | - `test/cookbooks/test/recipes/` - Test recipes for integration testing 131 | - `test/integration/` - InSpec integration test controls 132 | - `spec/unit/` - ChefSpec unit tests 133 | - `templates/` - ERB templates for configuration files 134 | - `documentation/` - Resource documentation 135 | 136 | ### Important Files 137 | - `metadata.rb` - Cookbook metadata and dependencies 138 | - `Berksfile` - Cookbook dependency management 139 | - `kitchen.yml` - Vagrant-based integration testing (local development) 140 | - `kitchen.dokken.yml` - Docker-based integration testing (CI) 141 | - `.rubocop.yml` - Ruby linting configuration 142 | - `.github/workflows/ci.yml` - Continuous integration pipeline 143 | 144 | ### Common Test Suites 145 | - `package` - Test package installation method 146 | - `source-default` - Test default source compilation 147 | - `source-24`, `source-26`, `source-28` - Test specific HAProxy versions 148 | - `config-2`, `config-acl`, `config-ssl-redirect` - Test various configurations 149 | - `source-lua` - Test Lua compilation support 150 | 151 | ## Cookbook Architecture 152 | 153 | ### Custom Resources Available 154 | - `haproxy_install` - Install HAProxy via package or source 155 | - `haproxy_service` - Manage HAProxy service 156 | - `haproxy_config_global` - Global configuration section 157 | - `haproxy_config_defaults` - Default configuration section 158 | - `haproxy_frontend` - Frontend configuration 159 | - `haproxy_backend` - Backend configuration 160 | - `haproxy_listen` - Listen section (combines frontend/backend) 161 | - `haproxy_acl` - Access Control Lists 162 | - `haproxy_userlist` - User authentication lists 163 | 164 | ### Installation Methods 165 | 1. **Package Installation**: Uses system packages (fastest, recommended for most users) 166 | 2. **Source Compilation**: Compiles HAProxy from source (slower, more flexible options) 167 | 168 | ## Development Workflow 169 | 170 | ### Making Changes 171 | 1. **Understand the resource**: Check `resources/` directory for the relevant resource file 172 | 2. **Check existing tests**: Look in `test/integration/` and `spec/unit/` for related tests 173 | 3. **Make minimal changes**: Modify only what's necessary 174 | 4. **Test locally**: Run linting and unit tests first 175 | 5. **Integration test**: Test with kitchen for the affected functionality 176 | 6. **Validate**: Ensure the resource works as expected in a real scenario 177 | 178 | ### Adding New Features 179 | 1. **Check existing resources**: See if functionality exists in another resource 180 | 2. **Follow patterns**: Use existing resources as templates for new ones 181 | 3. **Add tests**: Create both unit tests (ChefSpec) and integration tests (InSpec) 182 | 4. **Document**: Add or update documentation in `documentation/` directory 183 | 184 | ### Debugging Issues 185 | - Use `kitchen diagnose` to check test kitchen configuration 186 | - Use `kitchen login` to access test instances for debugging 187 | - Check `/var/log/chef/` in test instances for Chef run logs 188 | - Use `haproxy -c -f /etc/haproxy/haproxy.cfg` to validate HAProxy config syntax 189 | 190 | ## Platform Support 191 | - **Debian**: 11, 12 192 | - **Ubuntu**: 20.04, 22.04 193 | - **CentOS Stream**: 9 194 | - **Amazon Linux**: 2023 195 | 196 | Test changes across different platforms when modifying core installation or service logic. 197 | 198 | ## CI Pipeline Understanding 199 | The GitHub Actions CI runs: 200 | 1. **Lint-unit**: Cookstyle linting + ChefSpec unit tests (~5 minutes) 201 | 2. **Integration**: Kitchen tests across platform matrix (~1-2 hours total) 202 | 3. **Platform-specific**: Additional testing for Amazon Linux 203 | 204 | The pipeline tests all combinations of: 205 | - Multiple operating systems 206 | - Package vs source installation methods 207 | - Different HAProxy versions and configurations 208 | - Various use cases (ACL, SSL, Lua support, etc.) 209 | 210 | ## Common Pitfalls to Avoid 211 | - **DO NOT** run integration tests without Docker properly configured 212 | - **DO NOT** cancel long-running builds or tests - they take time to compile HAProxy 213 | - **DO NOT** modify resource partials in `resources/partial/` without understanding impacts 214 | - **DO NOT** change service resource without testing service management functionality 215 | - **ALWAYS** test both package and source installation methods if changing install logic 216 | - **ALWAYS** validate HAProxy configuration syntax when changing config generation 217 | 218 | ## Quick Reference Commands 219 | 220 | ```bash 221 | # Common file listing 222 | ls -la # Repository root contents 223 | ls resources/ # Available Chef resources 224 | ls test/integration/ # Integration test suites 225 | kitchen list # Available test instances 226 | 227 | # Quick validation 228 | cookstyle . | head -20 # Show first linting issues 229 | rspec spec/ --fail-fast # Stop on first test failure 230 | kitchen diagnose | grep -A5 platforms # Show test platforms 231 | ``` 232 | 233 | Use these instructions as your primary reference. Only search for additional information when encountering errors or missing details not covered here. -------------------------------------------------------------------------------- /.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: Dokken Integration Tests 3 | 4 | "on": 5 | pull_request: 6 | push: 7 | branches: [main] 8 | 9 | jobs: 10 | lint-unit: 11 | uses: sous-chefs/.github/.github/workflows/lint-unit.yml@5.0.5 12 | permissions: 13 | actions: write 14 | checks: write 15 | pull-requests: write 16 | statuses: write 17 | issues: write 18 | 19 | integration: 20 | needs: lint-unit 21 | runs-on: ubuntu-latest 22 | strategy: 23 | matrix: 24 | os: 25 | - "debian-11" 26 | - "debian-12" 27 | - "ubuntu-2004" 28 | - "ubuntu-2204" 29 | - "centos-stream-9" 30 | - "centos-stream-10" 31 | - "fedora-latest" 32 | suite: 33 | - config-2 34 | # - config-3 35 | - config-acl 36 | - config-array 37 | - config-backend-search 38 | - config-custom-template 39 | - config-fastcgi 40 | - config-resolver 41 | - config-ssl-redirect 42 | - "package" 43 | - "source-24" 44 | - "source-26" 45 | - "source-28" 46 | - "source-lua" 47 | - "source-default" 48 | # - "source-openssl" 49 | # OpenSSSL libraries are not currently compiling correctly 50 | # see https://github.com/sous-chefs/haproxy/issues/503 51 | fail-fast: false 52 | 53 | steps: 54 | - name: Check out code 55 | uses: actions/checkout@v5 56 | - name: Install Chef 57 | uses: actionshub/chef-install@main 58 | - name: Dokken 59 | uses: actionshub/test-kitchen@main 60 | env: 61 | CHEF_LICENSE: accept-no-persist 62 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 63 | with: 64 | suite: ${{ matrix.suite }} 65 | os: ${{ matrix.os }} 66 | 67 | integration-amazonlinux: 68 | needs: lint-unit 69 | runs-on: ubuntu-24.04 70 | strategy: 71 | matrix: 72 | os: 73 | - "amazonlinux-2023" 74 | suite: 75 | - "package" 76 | - "source-24" 77 | - "source-26" 78 | - "source-28" 79 | - "source-default" 80 | fail-fast: false 81 | 82 | steps: 83 | - name: Check out code 84 | uses: actions/checkout@v5 85 | - name: Install Chef 86 | uses: actionshub/chef-install@3.0.1 87 | - name: Dokken 88 | uses: actionshub/test-kitchen@3.0.0 89 | env: 90 | CHEF_LICENSE: accept-no-persist 91 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 92 | with: 93 | suite: ${{ matrix.suite }} 94 | os: ${{ matrix.os }} 95 | 96 | lua_test: 97 | needs: lint-unit 98 | runs-on: ubuntu-latest 99 | strategy: 100 | matrix: 101 | os: 102 | - "centos-stream-9" 103 | suite: 104 | - "source-lua" 105 | fail-fast: false 106 | 107 | steps: 108 | - name: Check out code 109 | uses: actions/checkout@v5 110 | - name: Install Chef 111 | uses: actionshub/chef-install@3.0.1 112 | - name: Dokken 113 | uses: actionshub/test-kitchen@3.0.0 114 | env: 115 | CHEF_LICENSE: accept-no-persist 116 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 117 | with: 118 | suite: ${{ matrix.suite }} 119 | os: ${{ matrix.os }} 120 | 121 | configtest: 122 | needs: lint-unit 123 | runs-on: ubuntu-latest 124 | strategy: 125 | matrix: 126 | os: 127 | - "centos-stream-9" 128 | suite: 129 | - "config-2" 130 | # - "config-3" 131 | - "config-backend-search" 132 | - "config-acl" 133 | - "config-resolver" 134 | - "config-ssl-redirect" 135 | - "config-custom-template" 136 | - "config-custom-template" 137 | - "config-array" 138 | - "config-fastcgi" 139 | fail-fast: false 140 | 141 | steps: 142 | - name: Check out code 143 | uses: actions/checkout@v5 144 | - name: Install Chef 145 | uses: actionshub/chef-install@3.0.1 146 | - name: Dokken 147 | uses: actionshub/test-kitchen@3.0.0 148 | env: 149 | CHEF_LICENSE: accept-no-persist 150 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 151 | with: 152 | suite: ${{ matrix.suite }} 153 | os: ${{ matrix.os }} 154 | -------------------------------------------------------------------------------- /.github/workflows/conventional-commits.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: conventional-commits 3 | 4 | "on": 5 | pull_request: 6 | types: 7 | - opened 8 | - reopened 9 | - edited 10 | - synchronize 11 | 12 | jobs: 13 | conventional-commits: 14 | uses: sous-chefs/.github/.github/workflows/conventional-commits.yml@5.0.5 15 | -------------------------------------------------------------------------------- /.github/workflows/copilot-setup-steps.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Copilot Setup Steps' 3 | 4 | "on": 5 | workflow_dispatch: 6 | push: 7 | paths: 8 | - .github/workflows/copilot-setup-steps.yml 9 | pull_request: 10 | paths: 11 | - .github/workflows/copilot-setup-steps.yml 12 | 13 | jobs: 14 | copilot-setup-steps: 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: read 18 | steps: 19 | - name: Check out code 20 | uses: actions/checkout@v5 21 | - name: Install Chef 22 | uses: actionshub/chef-install@main 23 | - name: Install cookbooks 24 | run: berks install 25 | -------------------------------------------------------------------------------- /.github/workflows/prevent-file-change.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: prevent-file-change 3 | 4 | "on": 5 | pull_request: 6 | types: 7 | - opened 8 | - reopened 9 | - edited 10 | - synchronize 11 | 12 | jobs: 13 | prevent-file-change: 14 | uses: sous-chefs/.github/.github/workflows/prevent-file-change.yml@5.0.5 15 | secrets: 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: release 3 | 4 | 5 | "on": 6 | push: 7 | branches: [main] 8 | 9 | permissions: 10 | contents: write 11 | issues: write 12 | pull-requests: write 13 | packages: write 14 | attestations: write 15 | id-token: write 16 | 17 | jobs: 18 | release: 19 | uses: sous-chefs/.github/.github/workflows/release-cookbook.yml@5.0.5 20 | secrets: 21 | token: ${{ secrets.PORTER_GITHUB_TOKEN }} 22 | supermarket_user: ${{ secrets.CHEF_SUPERMARKET_USER }} 23 | supermarket_key: ${{ secrets.CHEF_SUPERMARKET_KEY }} 24 | slack_bot_token: ${{ secrets.SLACK_BOT_TOKEN }} 25 | slack_channel_id: ${{ secrets.SLACK_CHANNEL_ID }} 26 | -------------------------------------------------------------------------------- /.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@v10 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 | no-multiple-blanks: 7 | maximum: 2 8 | ignores: 9 | - .github/copilot-instructions.md 10 | - .windsurf/** 11 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD024": { 3 | "siblings_only": true 4 | }, 5 | "MD012": false, 6 | "MD013": false 7 | } 8 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "12.4.12" 3 | } 4 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - cookstyle 3 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "chef-software.chef", 4 | "Shopify.ruby-lsp", 5 | "editorconfig.editorconfig", 6 | "DavidAnson.vscode-markdownlint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.windsurf/rules/definition-of-done.md: -------------------------------------------------------------------------------- 1 | --- 2 | trigger: model_decision 3 | description: When completing a task check the following are true 4 | --- 5 | 6 | - `cookstyle` does not return any syntax or style errors 7 | - markdownlint-cli2 "**/*.md" "!vendor" "!.venv" --fix 8 | - yamllint 9 | - `kitchen test` does not return any errors 10 | - run all suites 11 | - do not skip suites 12 | This gives us knowledge that we have not broken areas of the cookbook we are not currently changing (regression) 13 | No matter what we have done, even if you think it is outside our control, kitchen test must pass 14 | -------------------------------------------------------------------------------- /.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/ea3221caed2301279da8e8e1ff162ae46b80cf9e/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` | Enable PCRE regex support. Automatically selects PCRE2 for RHEL/CentOS/AlmaLinux/Rocky >= 10, PCRE for < 10, Amazon Linux, and Fedora. | `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/ea3221caed2301279da8e8e1ff162ae46b80cf9e/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_default 41 | run_list: 42 | - recipe[test::source] 43 | - name: source_lua 44 | run_list: 45 | - recipe[test::source_lua] 46 | - name: source_openssl 47 | run_list: 48 | - recipe[test::source_openssl] 49 | - name: config_2 50 | run_list: 51 | - recipe[test::config_2] 52 | - name: config_3 53 | run_list: 54 | - recipe[test::config_3] 55 | - name: config_4 56 | run_list: 57 | - recipe[test::config_4] 58 | - name: config_backend_search 59 | run_list: 60 | - recipe[test::config_backend_search] 61 | - name: config_acl 62 | run_list: 63 | - recipe[test::config_acl] 64 | - name: config_resolver 65 | run_list: 66 | - recipe[test::config_resolver] 67 | - name: config_ssl_redirect 68 | run_list: 69 | - recipe[test::config_ssl_redirect] 70 | - name: config_custom_template 71 | run_list: 72 | - recipe[test::config_custom_template] 73 | - name: config_array 74 | run_list: 75 | - recipe[test::config_array] 76 | - name: config_fastcgi 77 | run_list: 78 | - recipe[test::config_fastcgi] 79 | -------------------------------------------------------------------------------- /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 pcre_package_name 10 | # Use PCRE2 for RHEL/CentOS/AlmaLinux/Rocky >= 10 where PCRE1 is deprecated 11 | # Use PCRE for RHEL < 10, Amazon Linux, Fedora, and other platforms 12 | if platform_family?('rhel') && platform_version.to_i >= 10 13 | 'pcre2-devel' 14 | else 15 | 'pcre-devel' 16 | end 17 | end 18 | 19 | def source_package_list 20 | case node['platform_family'] 21 | when 'debian' 22 | %w(libpcre3-dev libssl-dev zlib1g-dev libsystemd-dev) 23 | when 'rhel', 'amazon', 'fedora' 24 | [pcre_package_name, 'openssl-devel', 'zlib-devel', 'systemd-devel', 'tar'] 25 | when 'suse' 26 | %w(pcre-devel libopenssl-devel zlib-devel systemd-devel) 27 | end 28 | end 29 | 30 | def ius_package 31 | { 32 | name: 'ius-release.rpm', 33 | url: 'https://repo.ius.io/ius-release-el7.rpm', 34 | } 35 | end 36 | 37 | def ius_platform_valid? 38 | platform_family?('rhel') && (platform_version.to_i == 6 || platform_version.to_i == 7) 39 | end 40 | 41 | def target_os(source_version) 42 | major_revision = node['kernel']['release'].split('.')[0..1].join('.').to_f 43 | minor_revision = node['kernel']['release'].split('.')[2].split('-').first.to_i 44 | 45 | if major_revision > 2.6 46 | source_version.chars.first == '1' ? 'linux2628' : 'linux-glibc' 47 | elsif major_revision == 2.6 48 | if minor_revision >= 28 49 | source_version.chars.first == '1' ? 'linux2628' : 'linux-glibc' 50 | else 51 | 'linux26' 52 | end 53 | else 54 | 'generic' 55 | end 56 | end 57 | 58 | def systemd_command(bin_prefix) 59 | if haproxy_version < 1.8 60 | ::File.join(bin_prefix, 'sbin', 'haproxy-systemd-wrapper') 61 | else 62 | ::File.join(bin_prefix, 'sbin', 'haproxy') + ' -Ws' 63 | end 64 | end 65 | 66 | def default_systemd_unit_content 67 | { 68 | 'Unit' => { 69 | 'Description' => 'HAProxy Load Balancer', 70 | 'Documentation' => 'file:/usr/share/doc/haproxy/configuration.txt.gz', 71 | 'After' => %w(network.target syslog.service), 72 | }, 73 | 'Service' => { 74 | 'EnvironmentFile' => '-/etc/default/haproxy', 75 | 'Environment' => "CONFIG=#{config_file} PIDFILE=/run/haproxy.pid", 76 | 'ExecStartPre' => "#{bin_prefix}/sbin/haproxy -f $CONFIG -c -q", 77 | 'ExecStart' => "#{systemd_command(bin_prefix)} -f $CONFIG -p $PIDFILE $OPTIONS", 78 | 'ExecReload' => [ 79 | "#{bin_prefix}/sbin/haproxy -f $CONFIG -c -q", 80 | '/bin/kill -USR2 $MAINPID', 81 | ], 82 | 'KillSignal' => 'TERM', 83 | 'User' => 'root', 84 | 'WorkingDirectory' => '/', 85 | 'KillMode' => 'mixed', 86 | 'Restart' => 'always', 87 | }, 88 | 'Install' => { 89 | 'WantedBy' => 'multi-user.target', 90 | }, 91 | } 92 | end 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /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.12' 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 | -------------------------------------------------------------------------------- /mise.toml: -------------------------------------------------------------------------------- 1 | # .mise.toml 2 | 3 | [env] 4 | PATH = "/opt/chef-workstation/bin:/opt/chef-workstation/embedded/bin:{{env.PATH}}" 5 | KITCHEN_LOCAL_YAML = "kitchen.dokken.yml" 6 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": { 4 | "package-name": "haproxy", 5 | "changelog-path": "CHANGELOG.md", 6 | "release-type": "ruby", 7 | "include-component-in-tag": false, 8 | "version-file": "metadata.rb" 9 | } 10 | }, 11 | "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" 12 | } 13 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ], 6 | "packageRules": [ 7 | { 8 | "groupName": "Actions", 9 | "matchUpdateTypes": [ 10 | "minor", 11 | "patch", 12 | "pin" 13 | ], 14 | "automerge": true, 15 | "addLabels": [ 16 | "Release: Patch", 17 | "Skip: Announcements" 18 | ] 19 | }, 20 | { 21 | "groupName": "Actions", 22 | "matchUpdateTypes": [ 23 | "major" 24 | ], 25 | "automerge": false, 26 | "addLabels": [ 27 | "Release: Patch", 28 | "Skip: Announcements" 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /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(&: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 | description: 'Enable PCRE support (automatically selects PCRE or PCRE2 based on platform)' 56 | 57 | property :use_promex, [true, false], 58 | default: false 59 | 60 | property :use_openssl, [true, false], 61 | default: true 62 | 63 | property :use_zlib, [true, false], 64 | default: true 65 | 66 | property :use_linux_tproxy, [true, false], 67 | default: true 68 | 69 | property :use_linux_splice, [true, false], 70 | default: true 71 | 72 | property :use_lua, [true, false], 73 | default: false 74 | 75 | property :lua_lib, String 76 | 77 | property :lua_inc, String 78 | 79 | property :ssl_lib, String 80 | 81 | property :ssl_inc, String 82 | 83 | property :use_systemd, [true, false], 84 | default: lazy { source_version.to_f >= 1.8 }, 85 | description: 'Evalues whether to use systemd based on the nodes init package' 86 | 87 | unified_mode true 88 | 89 | action_class do 90 | include Haproxy::Cookbook::ResourceHelpers 91 | end 92 | 93 | action_class do 94 | include Haproxy::Cookbook::Helpers 95 | include Haproxy::Cookbook::ResourceHelpers 96 | 97 | def compile_make_boolean(bool) 98 | bool ? '1' : '0' 99 | end 100 | 101 | def pcre_make_flag 102 | # Use PCRE2 for RHEL/CentOS/AlmaLinux/Rocky >= 10, PCRE for < 10 and other platforms 103 | pcre_package_name.include?('pcre2') ? 'USE_PCRE2' : 'USE_PCRE' 104 | end 105 | end 106 | 107 | action :install do 108 | case new_resource.install_type 109 | when 'package' 110 | case node['platform_family'] 111 | when 'amazon' 112 | include_recipe 'yum-epel' if new_resource.enable_epel_repo 113 | when 'rhel' 114 | include_recipe 'yum-epel' if new_resource.enable_epel_repo 115 | 116 | if new_resource.enable_ius_repo 117 | if ius_platform_valid? 118 | puts ius_package[:url] 119 | 120 | remote_file ::File.join(Chef::Config[:file_cache_path], ius_package[:name]) do 121 | source ius_package[:url] 122 | only_if { new_resource.enable_ius_repo } 123 | end 124 | 125 | package ius_package[:name] do 126 | source ::File.join(Chef::Config[:file_cache_path], ius_package[:name]) 127 | only_if { new_resource.enable_ius_repo } 128 | end 129 | else 130 | log 'This platform is not supported by IUS, ignoring enable_ius_repo property' do 131 | level :warn 132 | end 133 | end 134 | end 135 | end 136 | 137 | package new_resource.package_name do 138 | version new_resource.package_version if new_resource.package_version 139 | end 140 | when 'source' 141 | build_essential 'compilation tools' 142 | package source_package_list 143 | 144 | remote_file 'haproxy source file' do 145 | path ::File.join(Chef::Config[:file_cache_path], "haproxy-#{new_resource.source_version}.tar.gz") 146 | source new_resource.source_url 147 | checksum new_resource.source_checksum if new_resource.source_checksum 148 | action :create 149 | end 150 | 151 | make_cmd = "make TARGET=#{new_resource.source_target_os}" 152 | make_cmd << " CPU=#{new_resource.source_target_cpu}" if property_is_set?(:source_target_cpu) 153 | make_cmd << " ARCH=#{new_resource.source_target_arch}" if property_is_set?(:source_target_arch) 154 | make_cmd << " USE_LIBCRYPT=#{compile_make_boolean(new_resource.use_libcrypt)}" 155 | make_cmd << " #{pcre_make_flag}=1" if new_resource.use_pcre 156 | make_cmd << " USE_OPENSSL=#{compile_make_boolean(new_resource.use_openssl)}" 157 | make_cmd << " USE_ZLIB=#{compile_make_boolean(new_resource.use_zlib)}" 158 | make_cmd << " USE_LINUX_TPROXY=#{compile_make_boolean(new_resource.use_linux_tproxy)}" 159 | make_cmd << " USE_LINUX_SPLICE=#{compile_make_boolean(new_resource.use_linux_splice)}" 160 | make_cmd << " USE_SYSTEMD=#{compile_make_boolean(new_resource.use_systemd)}" 161 | make_cmd << " USE_LUA=#{compile_make_boolean(new_resource.use_lua)}" if new_resource.use_lua 162 | make_cmd << " USE_PROMEX=#{compile_make_boolean(new_resource.use_promex)}" if new_resource.use_promex 163 | make_cmd << " LUA_LIB=#{new_resource.lua_lib}" if property_is_set?(:lua_lib) 164 | make_cmd << " LUA_INC=#{new_resource.lua_inc}" if property_is_set?(:lua_inc) 165 | make_cmd << " SSL_LIB=#{new_resource.ssl_lib}" if property_is_set?(:ssl_lib) 166 | make_cmd << " SSL_INC=#{new_resource.ssl_inc}" if property_is_set?(:ssl_inc) 167 | # Add RPATH for custom SSL library to ensure runtime linking works correctly 168 | make_cmd << " LDFLAGS=-Wl,-rpath,#{new_resource.ssl_lib}" if property_is_set?(:ssl_lib) 169 | extra_cmd = ' EXTRA=haproxy-systemd-wrapper' if new_resource.source_version.to_f < 1.8 170 | 171 | bash 'compile_haproxy' do 172 | cwd Chef::Config[:file_cache_path] 173 | code <<-EOH 174 | tar xzf haproxy-#{new_resource.source_version}.tar.gz 175 | cd haproxy-#{new_resource.source_version} 176 | #{make_cmd} && make install PREFIX=#{new_resource.bin_prefix} #{extra_cmd} 177 | EOH 178 | not_if "#{::File.join(new_resource.bin_prefix, 'sbin', 'haproxy')} -v | grep #{new_resource.source_version}" 179 | end 180 | end 181 | 182 | with_run_context :root do 183 | group new_resource.group 184 | 185 | user new_resource.user do 186 | home "/home/#{new_resource.user}" 187 | group new_resource.group 188 | expire_date '2050-12-31' if Chef::VERSION.to_f >= 18.0 189 | inactive(-1) if Chef::VERSION.to_f >= 18.0 190 | end 191 | end 192 | end 193 | -------------------------------------------------------------------------------- /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 'option parameter with array of options' do 43 | recipe do 44 | haproxy_install 'package' 45 | 46 | haproxy_listen 'test_options' do 47 | bind '0.0.0.0:1337' 48 | mode 'http' 49 | option %w(dontlog-normal forwardfor) 50 | end 51 | end 52 | 53 | cfg_content = [ 54 | 'listen test_options', 55 | ' mode http', 56 | ' bind 0.0.0.0:1337', 57 | ' option dontlog-normal', 58 | ' option forwardfor', 59 | ] 60 | 61 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 62 | end 63 | 64 | context 'extra options hash with disabled option' do 65 | recipe do 66 | haproxy_install 'package' 67 | 68 | haproxy_listen 'disabled' do 69 | bind '0.0.0.0:1337' 70 | mode 'http' 71 | extra_options('disabled': '') 72 | end 73 | end 74 | 75 | cfg_content = [ 76 | 'listen disabled', 77 | ' mode http', 78 | ' bind 0.0.0.0:1337', 79 | ' disabled', 80 | ] 81 | 82 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 83 | end 84 | 85 | context 'extra options http-request rule should be placed before use_backend rule' do 86 | recipe do 87 | haproxy_install 'package' 88 | 89 | haproxy_listen 'use_backend' do 90 | bind '0.0.0.0:1337' 91 | mode 'http' 92 | use_backend ['admin0 if path_beg /admin0'] 93 | extra_options('http-request' => 'add-header Test Value') 94 | end 95 | end 96 | 97 | cfg_content = [ 98 | 'listen use_backend', 99 | ' mode http', 100 | ' bind 0.0.0.0:1337', 101 | ' http-request add-header Test Value', 102 | ' use_backend admin0 if path_beg /admin0', 103 | ] 104 | 105 | it { is_expected.to render_file('/etc/haproxy/haproxy.cfg').with_content(/#{cfg_content.join('\n')}/) } 106 | 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) } 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | # renovate: datasource=endoflife-date depName=haproxy versioning=semver 2 | version = '2.4.25' 3 | 4 | haproxy_install 'source' do 5 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 6 | source_checksum '44b035bdc9ffd4935f5292c2dfd4a1596c048dc59c5b25a0c6d7689d64f50b99' 7 | source_version version 8 | use_libcrypt true 9 | use_pcre true 10 | use_openssl true 11 | use_zlib true 12 | use_promex true 13 | use_linux_tproxy true 14 | use_linux_splice true 15 | end 16 | 17 | haproxy_config_global '' 18 | 19 | haproxy_config_defaults '' 20 | 21 | haproxy_service 'haproxy' do 22 | action :create 23 | delayed_action %i(enable start) 24 | end 25 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_26.rb: -------------------------------------------------------------------------------- 1 | # renovate: datasource=endoflife-date depName=haproxy versioning=semver 2 | version = '2.6.16' 3 | 4 | haproxy_install 'source' do 5 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 6 | source_checksum 'faac6f9564caf6e106fe22c77a1fb35406afc8cd484c35c2c844aaf0d7a097fb' 7 | source_version version 8 | use_libcrypt true 9 | use_pcre true 10 | use_openssl true 11 | use_zlib 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 %i(create enable start) 22 | end 23 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/source_28.rb: -------------------------------------------------------------------------------- 1 | # renovate: datasource=endoflife-date depName=haproxy versioning=semver 2 | version = '2.8.5' 3 | 4 | haproxy_install 'source' do 5 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 6 | source_checksum '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' 7 | source_version version 8 | use_libcrypt true 9 | use_pcre true 10 | use_openssl true 11 | use_zlib 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_28_pcre2.rb: -------------------------------------------------------------------------------- 1 | version = '2.8.5' 2 | 3 | # Test recipe for RHEL/CentOS platforms version 10 and above (uses PCRE2) 4 | haproxy_install 'source' do 5 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 6 | source_checksum '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' 7 | source_version version 8 | # Rely on auto-detection for PCRE2 on RHEL >= 10 9 | use_libcrypt true 10 | use_openssl true 11 | use_zlib 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 %i(create 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].to_s 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 | # renovate: datasource=endoflife-date depName=haproxy versioning=semver 55 | version = '2.4.25' 56 | 57 | haproxy_install 'source' do 58 | source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" 59 | source_checksum '44b035bdc9ffd4935f5292c2dfd4a1596c048dc59c5b25a0c6d7689d64f50b99' 60 | source_version version 61 | use_pcre true 62 | use_openssl true 63 | use_zlib true 64 | use_linux_tproxy true 65 | use_linux_splice true 66 | use_lua true 67 | lua_lib '/opt/lua-5.3.1/lib' 68 | lua_inc '/opt/lua-5.3.1/include' 69 | end 70 | 71 | haproxy_config_global '' 72 | 73 | haproxy_config_defaults '' 74 | 75 | haproxy_service 'haproxy' do 76 | action :create 77 | delayed_action %i(enable start) 78 | end 79 | -------------------------------------------------------------------------------- /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 | # renovate: datasource=endoflife-date depName=haproxy versioning=semver 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 | -------------------------------------------------------------------------------- /version.rb: -------------------------------------------------------------------------------- 1 | VERSION = '12.4.9'.freeze 2 | --------------------------------------------------------------------------------