├── .editorconfig ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS ├── lock.yml └── workflows │ ├── ci.yml │ └── stale.yml ├── .gitignore ├── .markdownlint-cli2.yaml ├── .mdlrc ├── .overcommit.yml ├── .vscode └── extensions.json ├── .yamllint ├── Berksfile ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dangerfile ├── LICENSE ├── README.md ├── TESTING.md ├── attributes └── default.rb ├── chefignore ├── documentation ├── .gitkeep └── resources │ ├── create_all_from_key.md │ ├── filebacked.md │ └── filesystem.md ├── examples └── example.json ├── kitchen.dokken.yml ├── kitchen.exec.yml ├── kitchen.global.yml ├── kitchen.yml ├── libraries └── fs.rb ├── metadata.rb ├── recipes ├── default.rb └── example.rb ├── renovate.json ├── resources ├── create_all_from_key.rb ├── default.rb └── filebacked.rb ├── spec ├── spec_helper.rb └── unit │ └── recipes │ └── default_spec.rb └── test ├── cookbooks └── test │ ├── README.md │ ├── metadata.rb │ └── recipes │ ├── default.rb │ └── nfs.rb └── integration └── default └── default_spec.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 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sous-chefs/maintainers 2 | -------------------------------------------------------------------------------- /.github/lock.yml: -------------------------------------------------------------------------------- 1 | --- 2 | daysUntilLock: 365 3 | exemptLabels: [] 4 | lockLabel: false 5 | lockComment: > 6 | This thread has been automatically locked since there has not been 7 | any recent activity after it was closed. Please open a new issue for 8 | related bugs. 9 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: ci 3 | 4 | "on": 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | lint-unit: 12 | uses: sous-chefs/.github/.github/workflows/lint-unit.yml@3.1.1 13 | permissions: 14 | actions: write 15 | checks: write 16 | pull-requests: write 17 | statuses: write 18 | issues: write 19 | 20 | integration: 21 | needs: "lint-unit" 22 | 23 | runs-on: ubuntu-latest 24 | strategy: 25 | matrix: 26 | os: 27 | - "centos-stream-8" 28 | - "centos-stream-9" 29 | - "debian-11" 30 | - "debian-12" 31 | - "ubuntu-2004" 32 | - "ubuntu-2204" 33 | suite: 34 | - "default" 35 | fail-fast: false 36 | 37 | steps: 38 | - name: Check out code 39 | uses: actions/checkout@v4 # v4 40 | - name: Install Chef 41 | uses: actionshub/chef-install@3.0.1 42 | - name: Dokken 43 | uses: actionshub/test-kitchen@3.0.0 44 | env: 45 | CHEF_LICENSE: accept-no-persist 46 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 47 | with: 48 | suite: ${{ matrix.suite }} 49 | os: ${{ matrix.os }} 50 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mark stale issues and pull requests 3 | 4 | "on": 5 | schedule: [cron: "0 0 * * *"] 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v9 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | close-issue-message: > 15 | Closing due to inactivity. 16 | If this is still an issue please reopen or open another issue. 17 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 18 | Thanks, Sous-Chefs. 19 | days-before-close: 7 20 | days-before-stale: 365 21 | stale-issue-message: > 22 | Marking stale due to inactivity. 23 | Remove stale label or comment or this will be closed in 7 days. 24 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 25 | Thanks, Sous-Chefs. 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | .config 3 | InstalledFiles 4 | pkg 5 | test/tmp 6 | test/version_tmp 7 | tmp 8 | _Store 9 | *~ 10 | *# 11 | .#* 12 | \#*# 13 | *.un~ 14 | *.tmp 15 | *.bk 16 | *.bkup 17 | 18 | # editor files 19 | .idea 20 | .*.sw[a-z] 21 | 22 | # ruby/bundler/rspec files 23 | .ruby-version 24 | .ruby-gemset 25 | .rvmrc 26 | Gemfile.lock 27 | .bundle 28 | *.gem 29 | coverage 30 | spec/reports 31 | 32 | # YARD / rdoc artifacts 33 | .yardoc 34 | _yardoc 35 | doc/ 36 | rdoc 37 | 38 | # chef infra stuff 39 | Berksfile.lock 40 | .kitchen 41 | kitchen.local.yml 42 | vendor/ 43 | .coverage/ 44 | .zero-knife.rb 45 | Policyfile.lock.json 46 | 47 | # vagrant stuff 48 | .vagrant/ 49 | .vagrant.d/ 50 | -------------------------------------------------------------------------------- /.markdownlint-cli2.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | ul-indent: false # MD007 3 | line-length: false # MD013 4 | no-duplicate-heading: false # MD024 5 | reference-links-images: false # MD052 6 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | 2 | rules "~MD013", "~MD024" 3 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "chef-software.chef", 4 | "rebornix.ruby", 5 | "editorconfig.editorconfig", 6 | "DavidAnson.vscode-markdownlint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | rules: 4 | line-length: 5 | max: 256 6 | level: warning 7 | document-start: disable 8 | braces: 9 | forbid: false 10 | min-spaces-inside: 0 11 | max-spaces-inside: 1 12 | min-spaces-inside-empty: -1 13 | max-spaces-inside-empty: -1 14 | comments: 15 | min-spaces-from-content: 1 16 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.chef.io' 2 | 3 | metadata 4 | 5 | group :integration do 6 | cookbook 'test', path: './test/cookbooks/test' 7 | end 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## Unreleased 6 | 7 | ## 4.2.2 - *2025-03-20* 8 | 9 | ## 4.2.1 - *2025-03-20* 10 | 11 | - Fix: initialise `label` local variable on creation of file system 12 | 13 | ## 4.2.0 - *2024-12-15* 14 | 15 | - Support use of symlinks for device paths 16 | 17 | ## 4.1.0 - *2024-12-09* 18 | 19 | - Add validation to the filesystem label property, limiting to a maximum length of 12 characters 20 | 21 | ## 4.0.15 - *2024-12-09* 22 | 23 | ## 4.0.14 - *2024-05-03* 24 | 25 | - Update tested platforms 26 | 27 | ## 4.0.13 - *2024-05-03* 28 | 29 | ## 4.0.12 - *2024-05-02* 30 | 31 | ## 4.0.11 - *2023-09-28* 32 | 33 | ## 4.0.10 - *2023-09-04* 34 | 35 | ## 4.0.9 - *2023-09-04* 36 | 37 | ## 4.0.8 - *2023-06-08* 38 | 39 | Standardise files with files in sous-chefs/repo-management 40 | 41 | ## 4.0.7 - *2023-05-17* 42 | 43 | ## 4.0.6 - *2023-05-03* 44 | 45 | ## 4.0.5 - *2023-04-01* 46 | 47 | ## 4.0.4 - *2023-03-02* 48 | 49 | ## 4.0.3 - *2023-02-14* 50 | 51 | ## 4.0.2 - *2023-02-14* 52 | 53 | ## 4.0.1 - *2022-10-28* 54 | 55 | - Fix document: `nomkfs` option is not in `filesystem` resource 56 | 57 | ## 4.0.0 - *2021-10-14* 58 | 59 | - Chef 17 compatibility 60 | - Minimum chef version set to 15.3 61 | 62 | ## 3.0.5 - *2021-08-31* 63 | 64 | - Standardise files with files in sous-chefs/repo-management 65 | 66 | ## 3.0.4 (2021-06-01) 67 | 68 | - Standardise files with files in sous-chefs/repo-management 69 | 70 | ## 3.0.3 (2020-11-09) 71 | 72 | - resolved cookstyle error: resources/default.rb:118:35 convention: `Style/RedundantCondition` 73 | - fix the check for an existing mountable filesystem before running mkfs again 74 | 75 | ## 3.0.2 (2020-09-16) 76 | 77 | - resolved cookstyle error: libraries/fs.rb:14:5 convention: `Style/RedundantAssignment` 78 | - resolved cookstyle error: libraries/fs.rb:15:1 convention: `Layout/EmptyLinesAroundMethodBody` 79 | - resolved cookstyle error: libraries/fs.rb:15:1 convention: `Layout/TrailingWhitespace` 80 | 81 | ## 3.0.1 (2020-08-07) 82 | 83 | - Fix README spelling errors and formatting 84 | 85 | ## 3.0.0 (2020-07-30) 86 | 87 | - Simplified the filesystem freeze action code 88 | - Added tests for the freeze action 89 | - Updated the versions of platforms to test against 90 | - Add the device_defer attribute to the filesystem resource. If set to true and the backing device does not exist the default resource returns without processing or error. 91 | - Convert the lwrp resources to custom resources 92 | - Add dokken cookbook converges and tests to the github flow 93 | 94 | ## 2.0.2 (2020-06-18) 95 | 96 | - Removed Dangerfile from rubocop.yml 97 | - Deleted rubocop.yml 98 | - Ran latest cookstyle to clean up minor style issues 99 | 100 | ## 2.0.1 - 2020-05-20 101 | 102 | - resolved cookstyle error: providers/filebacked.rb:36:14 refactor: `ChefModernize/ShellOutHelper` 103 | 104 | ## 2.0.0 - 2020-05-05 105 | 106 | - Require Chef Infra Client 14+ 107 | - Remove unused long_description metadata 108 | - Remove ChefSpec matchers that are autogenerated now 109 | - resolved cookstyle error: resources/create_all_from_key.rb:25:1 refactor: `ChefRedundantCode/UnnecessaryNameProperty` 110 | - resolved cookstyle error: resources/default.rb:25:1 refactor: `ChefRedundantCode/UnnecessaryNameProperty` 111 | - resolved cookstyle error: resources/filebacked.rb:25:1 refactor: `ChefRedundantCode/UnnecessaryNameProperty` 112 | - resolved cookstyle error: resources/filebacked.rb:26:1 convention: `Layout/EmptyLines` 113 | 114 | ## [1.0.0] - 2018-03-14 115 | 116 | - Fix idempotence of 'wait for device' block 117 | - Remove possible double format of disks if force 118 | - Do not perform test mount if ignore_existing and force 119 | - Use truthy value of ignore_existing rather than nil? 120 | - updated mount resource in providers/default.rb to notify directory resource immediately to fix mount permissions after mounting 121 | - Fix linting errors 122 | - Updated default provider to notify directory resource immediately upon mounting filesystem. (#37) 123 | - Reorganise code to only format disks once 124 | - Fix missing /etc/fstab file in centos7 image 125 | - Remove xfsprogs-devel 126 | 127 | ## [0.12.0] - 2017-04-24 128 | 129 | - removed xfs dependency, installing packages in default.rb 130 | 131 | ## [0.11.1] - 2017-03-20 132 | 133 | - fixed issue with frozen being a ruby default function 134 | 135 | ## [0.11.0] - 2017-03-13 136 | 137 | - Added CHANGELOG.md 138 | - Added CONTRIBUTING.md 139 | - Removed Berksfile.lock 140 | - Added CODE_OF_CONDUCT.md 141 | - Added Delivery 142 | - Added Travis 143 | - Added Test-Kitchen, Kitchen-dokken 144 | - updated Berksfile to supermarket 145 | - updated lvm >= 1.1 146 | - updated to sous-chefs 147 | 148 | ## [0.10.6] - 2016-01-21 149 | 150 | ## [0.10.2] - 2015-10-13 151 | 152 | - dont wait for network devices they won't exist 153 | - make fetches to fspackages not fail on unknown types 154 | 155 | ## Added 156 | 157 | [0.11.1]: https://github.com/sous-chefs/filesystem/compare/v0.11.0...v0.11.1 158 | [0.12.0]: https://github.com/sous-chefs/filesystem/compare/v0.11.1...v0.12.0 159 | [1.0.0]: https://github.com/sous-chefs/filesystem/compare/v0.12.0...v1.0.0 160 | -------------------------------------------------------------------------------- /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/master/CONTRIBUTING.MD](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/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 | -------------------------------------------------------------------------------- /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 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # filesystem cookbook 2 | 3 | [![Cookbook Version](https://img.shields.io/cookbook/v/filesystem.svg)](https://supermarket.chef.io/cookbooks/filesystem) 4 | [![CI State](https://github.com/sous-chefs/filesystem/workflows/ci/badge.svg)](https://github.com/sous-chefs/filesystem/actions?query=workflow%3Aci) 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 | This cookbook exists to generically define and create block device filesystems with the minimum of inputs. 10 | 11 | This cookbook supports four main types of block devices: 12 | 13 | - normal `device` - drives, SSDs, volumes presented by HBAs etc 14 | - device ID `uuid` - mostly found on drives / known block IDs. 15 | - LVM Volume Groups `vg` - found on systems using LVM. 16 | - file-backed `file` - created dynamically and looped back. 17 | 18 | We will try to create filesystems in two ways: through keys found in node data under 'filesystems' or by being called directly with the `filesystem` default provider. See the example recipe. 19 | 20 | You can also use your own key for a list of filesystems, see the example recipe for an example of this option. 21 | 22 | Tools have been listed in the following attribute key : filesystem_tools. This allows for extending the support to other/new filesystems. 23 | 24 | Network file systems, nfs and others, are somewhat supported. This cookbook will attempt to create a mount point, enable the filesystem by adding an `/etc/fstab` entry for the filesystem mount and will attempt to mount the filesystem. This cookbook does not attempt to modify the internal contents of network filesystems. 25 | 26 | ## Maintainers 27 | 28 | 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). 29 | 30 | ## Requirements 31 | 32 | - lvm cookbook when creating logical volumes 33 | - package #{fstype}progs to support your chosen fstype. We provide some defaults, too. 34 | 35 | ## Resources 36 | 37 | - [filesystem_create_all_from_key](https://github.com/sous-chefs/filesystem/blob/master/documentation/resources/create_all_from_key.md) - Create a filesystem, add a definition to fstab, mount the filesystem 38 | - [filesystem](https://github.com/sous-chefs/filesystem/blob/master/documentation/resources/filesystem.md) - Create a filesystem, add a definition to fstab, mount the filesystem 39 | - [filesystem_filebacked](https://github.com/sous-chefs/filesystem/blob/master/documentation/resources/filebacked.md) - Create a loopback filesystem 40 | 41 | ## Main Attributes 42 | 43 | ### `filesystems` 44 | 45 | Hash of filesytems to setup - this is called filesystems because filesystem is already created/managed by ohai (i.e. no s on the end). 46 | 47 | ### `node[:filesystems]` keys 48 | 49 | Each filesytem's key is the FS `label`: This explains each key in a filesystems entry. The label must not exceed 12 characters. 50 | 51 | We also let you use your own top-level key if you want - see the default recipe and example recipe. 52 | 53 | ## Usage 54 | 55 | Keyed filesystem creation: 56 | 57 | ````JSON 58 | { 59 | "filesystems": { 60 | "testfs1": { 61 | "device": "/dev/sdb", 62 | "mount": "/db", 63 | "fstype": "xfs", 64 | "options": "noatime,nodev", 65 | "mkfs_options": "-d sunit=128,swidth=2048" 66 | }, 67 | "applv1": { 68 | "mount": "/logical1", 69 | "fstype": "ext4", 70 | "vg": "standardvg", 71 | "size": "20G" 72 | }, 73 | "cluster_01": { 74 | "fstype": "ocfs2", 75 | "package": "ocfs2-tools", 76 | "device": "/dev/mpath/ocfs01", 77 | "mount": "/mnt/test" 78 | }, 79 | "filebacked": { 80 | "file": "/mnt/filesystem-on-a-filesystem.file", 81 | "device": "/dev/loop7", 82 | "mount": "/mnt/filesystem-on-a-filesystem", 83 | "size": "20000" 84 | } 85 | } 86 | } 87 | ```` 88 | 89 | ## Authors 90 | 91 | - Alex Trull 92 | - Jesse Nelson source of the original cookbook. 93 | 94 | ## Contributors 95 | 96 | This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false) 97 | 98 | ### Backers 99 | 100 | Thank you to all our backers! 101 | 102 | ![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40) 103 | 104 | ### Sponsors 105 | 106 | Support this project by becoming a sponsor. Your logo will show up here with a link to your website. 107 | 108 | ![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100) 109 | ![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100) 110 | ![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100) 111 | ![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100) 112 | ![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100) 113 | ![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100) 114 | ![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100) 115 | ![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100) 116 | ![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100) 117 | ![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100) 118 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Please refer to [the community cookbook documentation on testing](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/TESTING.MD). 4 | -------------------------------------------------------------------------------- /attributes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Attributes:: default 4 | # 5 | # Copyright:: 2013-2017, Alex Trull 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # This is used to create the filesystems themselves, see examples in the README. 21 | default['filesystems'] = {} 22 | 23 | # These are used to provide sensible default recipes and packages for installing tools for supporting filesystems. 24 | # The format is ['filesystem_tools']['fstype']['package|recipe'] = "package1,package2" 25 | default['filesystem_tools']['ext2']['package'] = 'e2fsprogs' 26 | default['filesystem_tools']['ext3']['package'] = 'e2fsprogs' 27 | default['filesystem_tools']['ext4']['package'] = 'e2fsprogs' 28 | default['filesystem_tools']['xfs']['package'] = 'xfsprogs' 29 | default['filesystem_tools']['btrfs']['package'] = 'btrfs-tools' 30 | # Different filesystems use different force options (stupid I know) 31 | default['filesystem_tools']['ext2']['forceopt'] = '-F' 32 | default['filesystem_tools']['ext3']['forceopt'] = '-F' 33 | default['filesystem_tools']['ext4']['forceopt'] = '-F' 34 | default['filesystem_tools']['xfs']['forceopt'] = '-f' 35 | default['filesystem_tools']['btrfs']['forceopt'] = '-f' 36 | -------------------------------------------------------------------------------- /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/filesystem/00837016485fa45201aa0d7daac8cb3d93336bea/documentation/.gitkeep -------------------------------------------------------------------------------- /documentation/resources/create_all_from_key.md: -------------------------------------------------------------------------------- 1 | # Resource: filesystem_create_all_from_key 2 | 3 | ## Actions 4 | 5 | | Action | Description | 6 | | ------ | --------------------- | 7 | | create | Create multiple filesystems based on node attributes | 8 | 9 | ## Properties 10 | 11 | ### `name` 12 | 13 | The resource looks in the node attribute for node[new_resource.name] or node['filesystems']. 14 | The cookbook assumes with will find a hash with a key (label) and value of a hash filesystem resource properties. 15 | Each label and set of filesystem properties is used to create a filesystem resource. 16 | 17 | ## Usage 18 | 19 | Keyed filesystem creation: 20 | 21 | ````JSON 22 | { 23 | "filesystems": { 24 | "testfs1": { 25 | "device": "/dev/sdb", 26 | "mount": "/db", 27 | "fstype": "xfs", 28 | "optons": "noatime,nobarrier", 29 | "mkfs_options": "-d sunit=128,swidth=2048" 30 | }, 31 | "applv1": { 32 | "mount": "/logical1", 33 | "fstype": "ext4", 34 | "vg": "standardvg", 35 | "size": "20G" 36 | }, 37 | "cluster_01": { 38 | "fstype": "ocfs2", 39 | "package": "ocfs2-tools", 40 | "device": "/dev/mpath/ocfs01", 41 | "mount": "/mnt/test" 42 | }, 43 | "filebacked": { 44 | "file": "/mnt/filesystem-on-a-filesystem.file", 45 | "device": "/dev/loop7", 46 | "mount": "/mnt/filesystem-on-a-filesystem", 47 | "size": "20000" 48 | } 49 | } 50 | } 51 | ```` 52 | -------------------------------------------------------------------------------- /documentation/resources/filebacked.md: -------------------------------------------------------------------------------- 1 | 2 | # Resource: filebacked 3 | 4 | ## Actions 5 | 6 | | Action | Description | 7 | | ------ | --------------------- | 8 | | create | Create a loopback filesystem backed by a file | 9 | 10 | ## Properties 11 | 12 | ### `name` 13 | 14 | The backing file name. 15 | 16 | ### `device` 17 | 18 | The loopback device name. 19 | 20 | ### `size` 21 | 22 | Size in M (1024x1014). 23 | 24 | ### `sparse` 25 | 26 | Fast file creation. The file is not filled with zeros. 27 | 28 | ## Usage 29 | 30 | ```ruby 31 | filesystem_filebacked '/tmp/myfile' do 32 | device /dev/loop1 33 | size 10 34 | sparse true 35 | end 36 | ``` 37 | -------------------------------------------------------------------------------- /documentation/resources/filesystem.md: -------------------------------------------------------------------------------- 1 | # Resource: filesystem 2 | 3 | ## Actions 4 | 5 | | Action | Description | 6 | | ------ | --------------------- | 7 | | create | Create a filesystem on a device | 8 | | enable | Add an entry for the filesystem mount to /etc/fstab | 9 | | mount | Mount the filesystem on a directory mount point | 10 | | freeze | Use fsfreeze to lock a filesystem | 11 | | unfreeze | Use fsfreeze to unlock a filesystem | 12 | 13 | ## Properties 14 | 15 | ### `label` 16 | 17 | Each filesytem's key is the FS `label`: The label must not exceed 12 characters. 18 | 19 | ## Filesystem Backing Location keys 20 | 21 | ### `device` 22 | 23 | Path to the device to create the filesystem upon. 24 | 25 | ### `uuid` 26 | 27 | UUID of the device to create the filesystem upon. 28 | 29 | ### `file` 30 | 31 | Path to the file-backed storage to be used for a loopback device. `device` must also be present to specify the loopback. If the `file` is not present it will be created, as long as a size is given. 32 | 33 | ### `vg` 34 | 35 | Name of the LVM volume group use as backing store for a logical volume. If not present it will be created, as long as a size is given. 36 | 37 | Each filesystem should be given one of these attributes for it to have a location to be created at. 38 | 39 | If none of these are present then we try to find a device at the label itself. 40 | 41 | ## Filesystem Creation Options 42 | 43 | ### `fstype` 44 | 45 | [ocfs2|ext3|ext4|etc] (default: ext3). The type is not verified. 46 | 47 | The type of filesystem to be created. 48 | 49 | ### `mkfs_options` unique for each filesystem 50 | 51 | Options to pass to mkfs at creation time. 52 | 53 | ## Filesystem Backing Options 54 | 55 | ### `size` 10000 (`file`) or 10%VG|10g (`vg`) 56 | 57 | The size, only used for filesystems backed by `vg` and `file` storage. If vg then a number suffixied by the scale [g|m|t|p], if a file then just a number [megabytes]. 58 | 59 | ### `sparse` Boolean (default: true) 60 | 61 | Sparse file creation, used by the `file` storage, by default we use this for speed, but you may not want that. 62 | 63 | ### `stripes` optional 64 | 65 | The stripes, only used for filesystems backed by `vg` aka LVM storage. 66 | 67 | ### `mirrors` optional 68 | 69 | The mirrors, only used for filesystems backed by `vg` aka LVM storage. 70 | 71 | ## Filesystem Mounting Options 72 | 73 | ### `mount` /path/to/mount 74 | 75 | Path to mount the filesystem. (If present we will mount the filesystem - this is rather important) 76 | 77 | ### `options` rw,noatime,defaults (default: defaults) 78 | 79 | Options to mount with and add to the fstab. 80 | 81 | ### `dump` 0|1|2 (default: 0) 82 | 83 | Dump entry for fstab 84 | 85 | ### `pass` 0|1|2 (default: 0) 86 | 87 | Pass entry for fstab 88 | 89 | ### `user` name 90 | 91 | Owner of the root directory of the filesystem, otherwise we use the chef default. We will not try to create users. You should use the users cookbook for that. 92 | 93 | ### `group` name 94 | 95 | Group of the root directory of the filesystem, otherwise we use the chef default. We will not try to create groups. You should write a cookbook to make them nicely. 96 | 97 | ### `mode` 775 98 | 99 | Mode of the root directory of the filesystem, otherwise we use the chef default. 100 | 101 | ## Package and Recipe Options 102 | 103 | ### `package` Package name to install, if specified 104 | 105 | Used to support the filesystem 106 | 107 | ### `recipe` Recipe to run, if specified - for future use, not currently supported from the custom resource 108 | 109 | Used to support the filesystem 110 | 111 | ## Atypical Behaviour Modifiers 112 | 113 | ### `device_defer` Skip file system creation if the backing device does not exist. Defaults to false 114 | 115 | ### `force` Boolean (default: false) 116 | 117 | Set to true we unsafely create filesystems. If there is data it will be lost. Should not use this unless you are quite confident. 118 | 119 | ### `ignore_existing` Boolean (default: false) 120 | 121 | Set to true we will ignore existing filesystems and recreate them. Double Dangerous and only for unsound behaviour. Use with 'force' true. 122 | 123 | ### `nomount` Boolean (default: false) 124 | 125 | Set to true to disable mounting of the filesystem. 126 | 127 | ### `noenable` Boolean (default: false) 128 | 129 | Set to true to disable adding to fstab. 130 | 131 | ## Usage 132 | 133 | Filesystem creation: 134 | 135 | ````RUBY 136 | filesystem "label" do 137 | fstype "ext3" 138 | device "/dev/sdb1" 139 | mount "/mnt/littlelabel" 140 | action [:create, :enable, :mount] 141 | end 142 | ```` 143 | -------------------------------------------------------------------------------- /examples/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "filesystems": { 3 | "mnt": { 4 | "device": "/dev/xvdb", 5 | "fstype": "ext3", 6 | "mount": "/mnt", 7 | "user": "root", 8 | "group": "root", 9 | "nomkfs": true 10 | }, 11 | "lvmbar1": { 12 | "vg": "foo", 13 | "fstype": "ext3", 14 | "mount": "/mnt/filesystems-testing/lvm-vg-foo-lv-lvmbar1", 15 | "options": "noatime,nobarrier", 16 | "mkfs_options": "-d sunit=128,swidth=2048", 17 | "size": "10%VG" 18 | }, 19 | "lvmbar2": { 20 | "vg": "foo", 21 | "fstype": "ext2", 22 | "mount": "/mnt/filesystems-testing/lvm-vg-foo-lv-lvmbar2", 23 | "size": "10%VG", 24 | "stripes": 2 25 | }, 26 | "lvmbar3": { 27 | "vg": "foo", 28 | "fstype": "ext4", 29 | "mount": "/mnt/filesystems-testing/lvm-vg-foo-lv-lvmbar3", 30 | "size": "10%VG", 31 | "stripes": 2, 32 | "mirrors": 2 33 | }, 34 | "nobody777": { 35 | "file": "/mnt/filesystems-testing/nobody777.file", 36 | "device": "/dev/loop0", 37 | "mount": "/mnt/filesystems-testing/nobody777", 38 | "user": "nobody", 39 | "group": "nogroup", 40 | "mode": "777", 41 | "noenable": true, 42 | "size": "1000" 43 | }, 44 | "sparsefalse": { 45 | "file": "/mnt/filesystems-testing/sparsefalse.file", 46 | "device": "/dev/loop1", 47 | "package": "e2fsprogs", 48 | "mount": "/mnt/filesystems-testing/sparsefalse", 49 | "noenable": true, 50 | "sparse": false, 51 | "size": "1000" 52 | }, 53 | "btrfs": { 54 | "fstype": "btrfs", 55 | "file": "/mnt/filesystems-testing/btrfs.file", 56 | "device": "/dev/loop2", 57 | "mount": "/mnt/filesystems-testing/btrfs", 58 | "noenable": true, 59 | "size": "1000" 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /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: amazonlinux-2023 21 | driver: 22 | image: dokken/amazonlinux-2023 23 | pid_one_command: /usr/lib/systemd/systemd 24 | 25 | - name: centos-7 26 | driver: 27 | image: dokken/centos-7 28 | pid_one_command: /usr/lib/systemd/systemd 29 | 30 | - name: centos-stream-8 31 | driver: 32 | image: dokken/centos-stream-8 33 | pid_one_command: /usr/lib/systemd/systemd 34 | 35 | - name: centos-stream-9 36 | driver: 37 | image: dokken/centos-stream-9 38 | pid_one_command: /usr/lib/systemd/systemd 39 | 40 | - name: debian-9 41 | driver: 42 | image: dokken/debian-9 43 | pid_one_command: /bin/systemd 44 | 45 | - name: debian-10 46 | driver: 47 | image: dokken/debian-10 48 | pid_one_command: /bin/systemd 49 | 50 | - name: debian-11 51 | driver: 52 | image: dokken/debian-11 53 | pid_one_command: /bin/systemd 54 | 55 | - name: debian-12 56 | driver: 57 | image: dokken/debian-12 58 | pid_one_command: /bin/systemd 59 | 60 | - name: fedora-latest 61 | driver: 62 | image: dokken/fedora-latest 63 | pid_one_command: /usr/lib/systemd/systemd 64 | 65 | - name: opensuse-leap-15 66 | driver: 67 | image: dokken/opensuse-leap-15 68 | pid_one_command: /usr/lib/systemd/systemd 69 | 70 | - name: oraclelinux-7 71 | driver: 72 | image: dokken/oraclelinux-7 73 | pid_one_command: /usr/lib/systemd/systemd 74 | 75 | - name: oraclelinux-8 76 | driver: 77 | image: dokken/oraclelinux-8 78 | pid_one_command: /usr/lib/systemd/systemd 79 | 80 | - name: oraclelinux-9 81 | driver: 82 | image: dokken/oraclelinux-9 83 | pid_one_command: /usr/lib/systemd/systemd 84 | 85 | - name: rockylinux-8 86 | driver: 87 | image: dokken/rockylinux-8 88 | pid_one_command: /usr/lib/systemd/systemd 89 | 90 | - name: rockylinux-9 91 | driver: 92 | image: dokken/rockylinux-9 93 | pid_one_command: /usr/lib/systemd/systemd 94 | 95 | - name: ubuntu-18.04 96 | driver: 97 | image: dokken/ubuntu-18.04 98 | pid_one_command: /bin/systemd 99 | 100 | - name: ubuntu-20.04 101 | driver: 102 | image: dokken/ubuntu-20.04 103 | pid_one_command: /bin/systemd 104 | 105 | - name: ubuntu-22.04 106 | driver: 107 | image: dokken/ubuntu-22.04 108 | pid_one_command: /bin/systemd 109 | 110 | - name: ubuntu-23.04 111 | driver: 112 | image: dokken/ubuntu-23.04 113 | pid_one_command: /bin/systemd 114 | -------------------------------------------------------------------------------- /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-7 22 | - name: centos-stream-8 23 | - name: centos-stream-9 24 | - name: debian-9 25 | - name: debian-10 26 | - name: debian-11 27 | - name: debian-12 28 | - name: fedora-latest 29 | - name: opensuse-leap-15 30 | - name: oraclelinux-7 31 | - name: oraclelinux-8 32 | - name: oraclelinux-9 33 | - name: rockylinux-8 34 | - name: rockylinux-9 35 | - name: ubuntu-18.04 36 | - name: ubuntu-20.04 37 | - name: ubuntu-22.04 38 | - name: ubuntu-23.04 39 | -------------------------------------------------------------------------------- /kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | provisioner: 6 | product_name: chef 7 | product_version: <%= ENV['CHEF_VERSION'] || 'latest' %> 8 | install_strategy: once 9 | deprecations_as_errors: true 10 | multiple_converge: 2 11 | 12 | verifier: 13 | name: inspec 14 | sudo: false 15 | 16 | platforms: 17 | - name: amazonlinux2 18 | driver_config: 19 | box: mvbcoding/awslinux 20 | - name: centos-8 21 | - name: debian-10 22 | - name: fedora-31 23 | - name: opensuse-leap-15.1 24 | - name: ubuntu-20.04 25 | - name: freebsd-12 26 | 27 | suites: 28 | - name: default 29 | run_list: 30 | - recipe[filesystem] 31 | - recipe[filesystem::example] 32 | - recipe[test] 33 | - recipe[test::nfs] 34 | -------------------------------------------------------------------------------- /libraries/fs.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | require 'chef/mixin/shell_out' 3 | 4 | module FilesystemMod 5 | include Chef::Mixin::ShellOut 6 | 7 | MOUNT_EX_FAIL = 32 unless const_defined?(:MOUNT_EX_FAIL) 8 | MOUNT_EX_BUSY = 1 unless const_defined?(:MOUNT_EX_BUSY) 9 | NET_FS_TYPES = %w(nfs nfs4 cifs smp nbd).freeze unless const_defined?(:NET_FS_TYPES) 10 | NFS_TYPES = %w(nfs nfs4).freeze unless const_defined?(:NFS_TYPES) 11 | 12 | def canonical_path(path) 13 | File.exist?(path) && File.realpath(path) || path 14 | end 15 | 16 | # Check to determine if a device is mounted. 17 | def mounted?(params = {}) 18 | params.is_a?(String) && params = { device: params } # backward compatibility 19 | 20 | mounts = File.readlines('/proc/mounts').map(&:split).map do |field| 21 | { 22 | device: field[0].start_with?('/dev/') && canonical_path(field[0]) || field[0], 23 | mountpoint: field[1], 24 | } 25 | end 26 | 27 | if params.key?(:device) && params.key?(:mountpoint) 28 | mounts.select do |mount| 29 | mount[:device] == canonical_path(params[:device]) && 30 | mount[:mountpoint] == params[:mountpoint].chomp('/') 31 | end.any? 32 | elsif params.key?(:device) 33 | mounts.select { |mount| mount[:device] == canonical_path(params[:device]) }.any? 34 | elsif params.key?(:mountpoint) 35 | mounts.select { |mount| mount[:mountpoint] == params[:mountpoint].chomp('/') }.any? 36 | else 37 | raise 'Invalid parameters passed to method "mounted?"' 38 | end 39 | end 40 | 41 | # Check to determine if the mount is frozen. 42 | # There is no really good way to determine if a file system is frozen. 43 | # Trying to remount the file system will return a FAIL or BUSY, we need to test for both but the results can be misleading 44 | def filesystem_frozen?(mount_loc) 45 | fields = File.readlines('/proc/mounts').map(&:split).detect { |field| field[1] == mount_loc } 46 | raise "#{mount_loc} not mounted" unless fields 47 | stat = shell_out('mount', '-o', "remount,#{fields[3]}", mount_loc) 48 | [MOUNT_EX_FAIL, MOUNT_EX_BUSY].include?(stat.exitstatus) ? true : false 49 | end 50 | 51 | # Check if provided filesystem type is netfs 52 | def netfs?(fstype) 53 | NET_FS_TYPES.include? fstype 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'filesystem' 2 | maintainer 'Sous Chefs' 3 | maintainer_email 'help@sous-chefs.org' 4 | description 'Installs/Configures various filesystems' 5 | license 'Apache-2.0' 6 | version '4.2.2' 7 | source_url 'https://github.com/sous-chefs/filesystem' 8 | issues_url 'https://github.com/sous-chefs/filesystem/issues' 9 | chef_version '>= 15.3' 10 | 11 | %w(redhat centos xenserver ubuntu debian scientific amazon).each do |os| 12 | supports os 13 | end 14 | 15 | depends 'lvm', '>= 1.1' 16 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Recipe:: default 4 | # 5 | # Copyright:: 2013-2017, Alex Trull 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | case node['platform_family'] 20 | when 'debian' 21 | package %w(xfsprogs xfsdump xfslibs-dev) 22 | when 'rhel', 'fedora' 23 | package %w(xfsprogs) 24 | end 25 | 26 | # We want to support LVM 27 | include_recipe 'lvm' unless platform_family?('freebsd') 28 | 29 | # If we have contents at the default location, we try to make the filesystems with the custom resources. 30 | filesystem_create_all_from_key 'filesystems' do 31 | action :create 32 | not_if { node['filesystems'].nil? || node['filesystems'].empty? } 33 | end 34 | -------------------------------------------------------------------------------- /recipes/example.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Recipe:: example 4 | # 5 | # Copyright:: 2013-2017, Alex Trull 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # There are several ways you could use this cookbook 21 | # This is the default recipe's contents: 22 | 23 | # We want to support LVM 24 | include_recipe 'lvm' 25 | 26 | # If we have contents at the default location, we try to make the filesystems with the custom resources. 27 | filesystem_create_all_from_key 'filesystems' do 28 | action :create 29 | end 30 | 31 | ## Examples: 32 | 33 | # But there are always ways to do non-defaulty things 34 | 35 | # If we have contents at a different location we try and make all those other filesystems to. 36 | filesystem_create_all_from_key 'mylittlefilesystems' do 37 | action :create 38 | end 39 | 40 | # Or we can call the creation of a filesystem directly with the filesystem default custom resources 41 | # filesystem 'littlelabel' do 42 | # fstype 'ext3' 43 | # device '/dev/sdb1' 44 | # mount '/mnt/littlelabel' 45 | # action [:create, :enable, :mount] 46 | # end 47 | 48 | # Or what about in combination with the mdadm provider ? 49 | # mdadm "/dev/sd0" do 50 | # devices [ "/dev/s1", "/dev/s2", "/dev/s3", "/dev/s4" ] 51 | # level 5 52 | # action :create 53 | # end 54 | 55 | # filesystem "raid" do 56 | # fstype "ext4" 57 | # device "/dev/sd0" 58 | # mount "/mnt/raid" 59 | # action [:create, :enable, :mount] 60 | # end 61 | -------------------------------------------------------------------------------- /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/create_all_from_key.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Resource:: create_all_from_key 4 | # 5 | # Copyright:: 2013-2017, Alex Trull 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # We default to creating all filesystems found in the key 21 | unified_mode true 22 | 23 | action :create do 24 | # Our key is the new resource name or if not we go with filesystems 25 | # The key is a node attribute name 26 | key = @new_resource.name || 'filesystems' 27 | 28 | # We get our filesystems from the key in node data 29 | filesystems_to_be_created = node[key] || {} 30 | 31 | # For reach filesystem we want to make, we enter the main creation loop of calling the default filesystem provider. 32 | filesystems_to_be_created.each_key do |label| 33 | fs = filesystems_to_be_created[label] 34 | 35 | # We pass all possible options to the custom resource that creates, enables and mounts filesystems. 36 | filesystem label do 37 | label fs['label'] if fs['label'] 38 | device fs['device'] if fs['device'] 39 | vg fs['vg'] if fs['vg'] 40 | file fs['file'] if fs['file'] 41 | uuid fs['uuid'] if fs['uuid'] 42 | fstype fs['fstype'] if fs['fstype'] 43 | mkfs_options fs['mkfs_options'] if fs['mkfs_options'] 44 | recipe fs['recipe'] if fs['recipe'] 45 | package fs['package'] if fs['package'] 46 | sparse fs['sparse'] if fs['sparse'] 47 | size fs['size'] if fs['size'] 48 | stripes fs['stripes'] if fs['stripes'] 49 | mirrors fs['mirrors'] if fs['mirrors'] 50 | mount fs['mount'] if fs['mount'] 51 | options fs['options'] if fs['options'] 52 | user fs['user'] if fs['user'] 53 | group fs['group'] if fs['group'] 54 | mode fs['mode'] if fs['mode'] 55 | pass fs['pass'] if fs['pass'] 56 | dump fs['dump'] if fs['dump'] 57 | force fs['force'] if fs['force'] 58 | # We may not want to do the default action 59 | if fs['mount'] && fs['nomount'] 60 | # We are not mounting the fs, but we do enable its fstab entry. 61 | action [:create, :enable] 62 | elsif fs['mount'] && fs['noenable'] 63 | # We we not enable the fs in fstab, but we do mount it. 64 | action [:create, :mount] 65 | elsif fs['nomkfs'] 66 | # We don't create - we just mount and enable - like the mount resource would do. 67 | action [:enable, :mount] 68 | elsif fs['mount'] 69 | # Default expected behiavour - create, enable and mount 70 | action [:create, :enable, :mount] 71 | else 72 | # Non-default expected behavior if no mountpoint is given : we only create the filesystem, nothing else. 73 | action [:create] 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /resources/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Resource:: default 4 | # 5 | # Copyright:: 2013-2017, Alex Trull 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # Our filesystem provider creates filesystems and can also mount/enable them. 21 | default_action :create 22 | 23 | # The name property is the label of the filesystem. 24 | property :label, String, name_property: true, regex: /^.{1,12}$/ 25 | 26 | # We have several kinds of device we might be using 27 | property :device, String 28 | property :vg, String 29 | property :file, String 30 | property :uuid, String 31 | 32 | # Creation Options 33 | property :fstype, String, default: 'ext3' 34 | property :mkfs_options, String, default: '' 35 | property :package, String 36 | property :recipe, String 37 | property :device_defer, [true, false], default: false 38 | 39 | # LVM and filebacked 40 | property :sparse, [true, false], default: true 41 | property :size, String 42 | property :stripes, Integer 43 | property :mirrors, Integer 44 | 45 | # Mounting Options 46 | property :mount, String 47 | property :options, String, default: 'defaults' 48 | # Mount directory options 49 | property :user, String 50 | property :group, String 51 | property :mode, String 52 | # Fstab parts 53 | property :pass, Integer, default: 0, equal_to: [0, 1, 2] 54 | property :dump, Integer, default: 0, equal_to: [0, 1, 2] 55 | 56 | # We may try and force things with mkfs, danger... 57 | property :force, [true, false], default: false 58 | # An additional thing to ignore existing filesystems - this will actively lose you data on unmounted filesystems if set. 59 | property :ignore_existing, [true, false], default: false 60 | 61 | unified_mode true 62 | 63 | action_class do 64 | include FilesystemMod 65 | 66 | def wait_for_device 67 | count = 0 68 | until ::File.exist?(device) 69 | count += 1 70 | sleep 0.3 71 | Chef::Log.debug "waiting for #{device} to exist, try # #{count}" 72 | if count >= 1000 73 | # TODO: make this a parameter 74 | raise Timeout::Error, 'Timeout waiting for device' 75 | end 76 | end 77 | end 78 | 79 | def device 80 | @device ||= if @new_resource.file 81 | @new_resource.device 82 | elsif @new_resource.vg 83 | "/dev/mapper/#{@new_resource.vg}-#{new_resource.label}" 84 | elsif @new_resource.uuid 85 | "/dev/disk/by-uuid/#{@new_resource.uuid}" 86 | elsif @new_resource.device 87 | @new_resource.device 88 | else 89 | "/dev/mapper/#{new_resource.label}" 90 | end 91 | end 92 | 93 | # create the mount point directory 94 | # mount points should not have files in them and have no 95 | # reason to be user writable 96 | def mount_point(mount_location) 97 | directory "Mount point for #{mount_location}" do 98 | path mount_location 99 | recursive true 100 | owner 'root' 101 | group 'root' 102 | mode '755' 103 | not_if { Pathname.new(mount_location).mountpoint? } 104 | end 105 | end 106 | end 107 | 108 | action :create do 109 | label = @new_resource.label 110 | fstype = @new_resource.fstype 111 | mkfs_options = @new_resource.mkfs_options 112 | ignore_existing = @new_resource.ignore_existing 113 | vg = @new_resource.vg 114 | file = @new_resource.file 115 | sparse = @new_resource.sparse 116 | size = @new_resource.size 117 | stripes = @new_resource.stripes || nil 118 | mirrors = @new_resource.mirrors ? @new_resource.stripes : nil 119 | package = @new_resource.package 120 | force = @new_resource.force 121 | 122 | # In two cases we may need to idempotently create the storage before creating the filesystem on it: LVM and file-backed. 123 | if (vg || file) && !size.nil? 124 | 125 | # LVM 126 | # We use the lvm provider directly. 127 | lvm_logical_volume label do 128 | action :create 129 | group vg 130 | size size 131 | stripes unless stripes.nil? 132 | mirrors unless mirrors.nil? 133 | not_if do 134 | vg.nil? 135 | end 136 | end 137 | 138 | # File-backed 139 | # We use the local filebackend provider, to which we feed some variables including the loopback device we want. 140 | backed_device = device 141 | filesystem_filebacked file do 142 | action :create 143 | device backed_device 144 | size size 145 | sparse sparse 146 | not_if do 147 | file.nil? 148 | end 149 | end 150 | elsif new_resource.device_defer && !::File.exist?(device) && !FilesystemMod::NET_FS_TYPES.include?(fstype) 151 | return 152 | end 153 | 154 | wait_for_device unless ::File.exist?(device) || netfs?(fstype) 155 | 156 | # We only try and create a filesystem if the device exists and is unmounted 157 | unless mounted?(device: device) 158 | 159 | # Install the filesystem's default package and recipes as configured in default attributes. 160 | fs_tools = node['filesystem_tools'].fetch(fstype, nil) 161 | 162 | if fs_tools && fs_tools.fetch('package', false) 163 | packages = fs_tools['package'].split(',') 164 | packages.each { |default_package| package default_package.to_s } 165 | end 166 | if package 167 | packages = @new_resource.package.split(',') 168 | packages.each { |keyed_package| package keyed_package.to_s } 169 | end 170 | 171 | Chef::Log.info "filesystem #{label} creating #{fstype} on #{device}" 172 | 173 | # Install the filesystem's default package and recipes as configured in default attributes. 174 | mkfs_force_options = node['filesystem_tools'].fetch(fstype, nil) 175 | # One day Chef will support calling dynamic include_recipe from custom resources but until then - see https://tickets.opscode.com/browse/CHEF-611 176 | # (fs_tools['recipe'].split(',') || []).each {|default_recipe| include_recipe #{default_recipe}"} 177 | if mkfs_force_options && mkfs_force_options.fetch('forceopt', false) 178 | # if force is true, we set the force option. If it isn't set it remains empty. 179 | force_option = force ? mkfs_force_options['forceopt'] : '' 180 | end 181 | 182 | # Check to see if the existing file system is mountable 183 | generic_check_cmd = "mkdir -p /tmp/filesystemchecks/#{label}; mount #{device} /tmp/filesystemchecks/#{label} && umount /tmp/filesystemchecks/#{label}" 184 | generic_check = shell_out(generic_check_cmd) 185 | 186 | # We form our mkfs command 187 | mkfs_cmd = "mkfs -t #{fstype} #{force_option} #{mkfs_options} -L #{label} #{device}" 188 | 189 | if force 190 | # force rebuilt requires both force and ignore_existing to be set 191 | return if generic_check.exitstatus == 0 && !ignore_existing 192 | else 193 | # Don't remake the file system if it already exists 194 | return if generic_check.exitstatus == 0 195 | # Remake only if the right mkfs exists 196 | return if !shell_out("which mkfs.#{fstype}").exitstatus == 0 197 | end 198 | # We create the filesystem, but only if the device does not already contain a mountable filesystem, and we have the tools. 199 | converge_by("Mkfs type #{fstype} #{label} #{device}") do 200 | shell_out!(mkfs_cmd) 201 | end 202 | 203 | end 204 | end 205 | 206 | # If we're enabling, we create the fstab entry. 207 | action :enable do 208 | mount = @new_resource.mount 209 | fstype = @new_resource.fstype 210 | pass = @new_resource.pass 211 | dump = @new_resource.dump 212 | options = @new_resource.options 213 | file = @new_resource.file 214 | 215 | if mount 216 | 217 | mount_point(mount) 218 | 219 | # Substitute the device with the file when in loopback mode. 220 | # This should allow the mount to come back up on reboot. 221 | device_or_file = device 222 | if file && device.start_with?('/dev/loop') 223 | device_or_file = file 224 | options = [options, "loop=#{device}"].compact.join(',') 225 | end 226 | 227 | return if new_resource.device_defer && !::File.exist?(device) && !FilesystemMod::NET_FS_TYPES.include?(fstype) 228 | 229 | # Update fstab using the chef mount resource 230 | mount mount do 231 | action :enable 232 | device device_or_file 233 | pass pass 234 | dump dump 235 | fstype fstype 236 | options options 237 | end 238 | 239 | end 240 | end 241 | 242 | # If we're mounting, we mount. 243 | action :mount do 244 | mount = @new_resource.mount 245 | fstype = @new_resource.fstype 246 | user = @new_resource.user 247 | group = @new_resource.group 248 | options = @new_resource.options 249 | 250 | if mount 251 | 252 | mount_point(mount) 253 | 254 | return if new_resource.device_defer && !::File.exist?(device) && !FilesystemMod::NET_FS_TYPES.include?(fstype) 255 | 256 | # Mount using the chef resource 257 | mnt_device = device 258 | mount mount do 259 | device mnt_device 260 | fstype fstype 261 | options options 262 | action :mount 263 | not_if { mounted?(device: device, mountpoint: mount) } 264 | end 265 | 266 | # set directory attributes within the mounted file system 267 | # assume root has access to the mounted file system 268 | # do not change directory settings for NETWORK mounted file systems 269 | # NFS4 file systems in particular should not allow root access 270 | unless FilesystemMod::NET_FS_TYPES.include?(fstype) 271 | directory mount do 272 | path mount 273 | recursive true 274 | owner user 275 | group group 276 | mode mode 277 | only_if { Pathname.new(mount).mountpoint? } 278 | end 279 | end 280 | end 281 | end 282 | 283 | action :freeze do 284 | mount = @new_resource.mount 285 | raise 'mount not specified' if mount.nil? 286 | 287 | unless filesystem_frozen?(mount) 288 | converge_by("Freeze #{mount}") do 289 | shell_out!("fsfreeze --freeze #{mount}") 290 | end 291 | end 292 | end 293 | 294 | action :unfreeze do 295 | mount = @new_resource.mount 296 | raise 'mount not specified' if mount.nil? 297 | 298 | if filesystem_frozen?(mount) 299 | converge_by("Unfreeze #{mount}") do 300 | shell_out!("fsfreeze --unfreeze #{mount}") 301 | end 302 | end 303 | end 304 | -------------------------------------------------------------------------------- /resources/filebacked.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Resource:: filebacked 4 | # 5 | # Copyright:: 2013-2017, Alex Trull 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # We default to creating the file backed loopback. 21 | default_action :create 22 | 23 | # The name property is the file to be created. 24 | 25 | property :device, String 26 | property :size, String 27 | property :sparse, [true, false], default: true 28 | unified_mode true 29 | 30 | action :create do 31 | file = @new_resource.name 32 | size = @new_resource.size 33 | sparse = @new_resource.sparse 34 | device = @new_resource.device 35 | 36 | # Idempotent behaviour: 37 | 38 | # Case 1) File found, Loopback found => return loopback. 39 | # Case 2) File found, Loopback missing => create loopback, return loopback. 40 | # Case 3) File missing, Loopback missing => create file and loopback, return loopback. 41 | 42 | create_loopback = "losetup #{device} #{file}" 43 | 44 | get_loopback_cmd = "losetup -a | grep #{file} | grep #{device}" 45 | 46 | loopback = shell_out(get_loopback_cmd).stdout.gsub(/: \[.*/, '').strip 47 | 48 | if ::File.exist?(file) && device == loopback 49 | # Case 1) 50 | # File and Loopback found - nothing to do. 51 | 52 | elsif ::File.exist?(file) && device != loopback 53 | # Case 2) 54 | # File but no loopback - so we make a loopback 55 | 56 | # how is ls file returning 0 different from ::File.exist?(file) 57 | # if "ls #{file} >/dev/null" 58 | converge_by("Creating #{device} for #{file}") do 59 | shell_out!(create_loopback) 60 | end 61 | # end 62 | 63 | elsif !size.nil? 64 | # Case 3) 65 | # If we have a size, we can create the file.. 66 | 67 | # We make sure a directory exists for the file to live in. 68 | directory ::File.dirname(file) do 69 | recursive true 70 | end 71 | 72 | # We pick the file creation method 73 | file_creation_cmd = if sparse 74 | # We default to speedy file creation. 75 | "dd bs=1M count=0 seek=#{size} of=\"#{file}\"" 76 | else 77 | # If not sparse we use zeros - this takes much longer. 78 | "dd bs=1M count=#{size} if=/dev/zero of=\"#{file}\"" 79 | end 80 | 81 | # We create the file 82 | # File should not exist at this point 83 | # If the file was created, we make a loopback device for the file and return the loopback result. 84 | converge_by("Creating #{file} and device #{device}") do 85 | shell_out!(file_creation_cmd) 86 | shell_out!(create_loopback) 87 | end 88 | 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /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/default_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: filesystem 3 | # Spec:: default 4 | # 5 | # Copyright:: 2017, The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'filesystem::default' do 10 | context 'When all attributes are default, on an unspecified platform' do 11 | let(:chef_run) do 12 | runner = ChefSpec::ServerRunner.new(platform: 'ubuntu', version: '16.04') 13 | runner.converge(described_recipe) 14 | end 15 | 16 | it 'converges successfully' do 17 | expect { chef_run }.to_not raise_error 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/cookbooks/test/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sous-chefs/filesystem/00837016485fa45201aa0d7daac8cb3d93336bea/test/cookbooks/test/README.md -------------------------------------------------------------------------------- /test/cookbooks/test/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'test' 2 | maintainer 'Sous Chefs' 3 | maintainer_email 'help@sous-chefs.org' 4 | license 'All rights reserved' 5 | description 'Installs/Configures test' 6 | version '0.1.0' 7 | 8 | depends 'filesystem' 9 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: default 4 | # 5 | 6 | if platform_family?('debian') 7 | package 'mount' 8 | end 9 | 10 | if platform_family?('rhel') 11 | package 'e2fsprogs' 12 | end 13 | 14 | file '/etc/fstab' do 15 | action :touch 16 | end 17 | 18 | filesystem 'loop-1' do 19 | fstype 'ext3' 20 | file '/opt/loop.img' 21 | size '10000' 22 | device '/dev/loop5' 23 | mount '/mnt/loop-1' 24 | action [:create, :enable, :mount] 25 | end 26 | 27 | filesystem 'loop-2' do 28 | fstype 'ext3' 29 | file '/opt/loop.img' 30 | size '10000' 31 | device '/dev/loop6' 32 | mount '/mnt/loop-2' 33 | action [:create, :enable, :mount, :freeze] 34 | end 35 | 36 | filesystem 'loop-3' do 37 | fstype 'ext3' 38 | file '/opt/loop.img' 39 | size '10000' 40 | device '/dev/loop7' 41 | mount '/mnt/loop-3' 42 | action [:create, :enable, :mount, :freeze, :unfreeze] 43 | end 44 | 45 | filesystem 'dev1' do 46 | device_defer true 47 | fstype 'ext3' 48 | size '10000' 49 | device '/dev/dev1' 50 | mount '/mnt/dev-1' 51 | action [:create, :enable, :mount] 52 | end 53 | 54 | filesystem 'uuid1' do 55 | device_defer true 56 | fstype 'ext3' 57 | size '10000' 58 | uuid 'devuuid' 59 | mount '/mnt/uuid-1' 60 | action [:create, :enable, :mount] 61 | end 62 | 63 | filesystem 'label1' do 64 | device_defer true 65 | fstype 'ext3' 66 | size '10000' 67 | label 'label1' 68 | mount '/mnt/label-1' 69 | action [:create, :enable, :mount] 70 | end 71 | 72 | # verify the idempotence of filesystem initialization 73 | # add a file 74 | # unmount it 75 | # create the file system again - should not run mkfs again which would wipe out the filet 76 | 77 | file '/mnt/loop-1/testfile' 78 | 79 | mount '/mnt/loop-1 unmount' do 80 | action :unmount 81 | device '/dev/loop5' 82 | mount_point '/mnt/loop-1' 83 | end 84 | 85 | filesystem 'loop-1 remount' do 86 | fstype 'ext3' 87 | file '/opt/loop.img' 88 | label 'loop-1' 89 | size '10000' 90 | device '/dev/loop5' 91 | mount '/mnt/loop-1' 92 | action [:create, :enable, :mount] 93 | end 94 | -------------------------------------------------------------------------------- /test/cookbooks/test/recipes/nfs.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: nfs 4 | # 5 | 6 | return unless platform_family?('debian') 7 | 8 | # apt update 9 | apt_update 'Update packages' 10 | 11 | filesystem 'nfs-1' do 12 | fstype 'nfs' 13 | device 'localhost:/exports/nfs1' 14 | mount '/mnt/nfs-1' 15 | action [:enable] 16 | end 17 | 18 | filesystem 'nfs-4' do 19 | fstype 'nfs4' 20 | device 'localhost:/exports/nfs1' 21 | mount '/mnt/nfs-4' 22 | action [:enable] 23 | end 24 | -------------------------------------------------------------------------------- /test/integration/default/default_spec.rb: -------------------------------------------------------------------------------- 1 | describe file('/opt/loop.img') do 2 | it { should be_file } 3 | it { should exist } 4 | its('size') { should > 1 } 5 | end 6 | 7 | describe directory('/mnt/loop-1') do 8 | it { should exist } 9 | it { should be_directory } 10 | end 11 | 12 | describe mount('/mnt/loop-1') do 13 | it { should be_mounted } 14 | its('device') { should eq '/dev/loop5' } 15 | its('type') { should eq 'ext3' } 16 | end 17 | 18 | describe file('/mnt/loop-1/testfile') do 19 | it { should exist } 20 | it { should be_file } 21 | end 22 | 23 | if os.family == 'debian' 24 | describe etc_fstab.where { mount_point == '/mnt/nfs-1' } do 25 | its('file_system_type') { should cmp 'nfs' } 26 | end 27 | describe etc_fstab.where { mount_point == '/mnt/nfs-4' } do 28 | its('file_system_type') { should cmp 'nfs4' } 29 | end 30 | end 31 | --------------------------------------------------------------------------------