[
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--- Provide a general summary of your changes in the Title above -->\n\n## Description\n\n<!--- Describe your changes in detail -->\n\n## Motivation and Context\n\n<!--- Why is this change required? What problem does it solve? -->\n<!--- If it fixes an open issue, please link to the issue here. -->\n\n## How Has This Been Tested?\n\n<!--- Please describe in detail how you tested your changes. -->\n<!--- See how your change affects other areas of the code, etc. -->\n\n## Checklist:\n\n<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->\n<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->\n\n- [ ] My change requires a change to the documentation or CHANGELOG.\n- [ ] I have updated the CHANGELOG.md accordingly.\n- [ ] I have created a feature (non-master) branch for my PR."
  },
  {
    "path": ".github/workflows/build.yaml",
    "content": "name: Build\n\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - main\n    paths-ignore:\n      - .github/**\n      - docs/**\n      - LICENSES/**\n      - README.md\n      - mkdocs.yaml\n  workflow_run:\n    workflows: [CI]\n    types: [completed]\n    branches: [main]\n\npermissions:\n  contents: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event.workflow_run.conclusion == 'success' }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          fetch-tags: true\n\n      - uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n          check-latest: true\n          cache: true\n\n      - name: Create Helm Compose Distributions\n        run: make dist\n\n      - uses: actions/upload-artifact@v4\n        with:\n          name: helm-compose\n          path: release/*\n\n      - name: Publish release\n        if: \"contains(github.event.head_commit.message, 'docs: release')\"\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          TAG=$(git describe --abbrev=0)\n\n          for FILE in release/*.tgz; do \n            gh release upload ${TAG} ${FILE} --clobber\n          done\n\n          gh release edit ${TAG} --latest --prerelease=false\n\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "name: CI\n\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n          check-latest: true\n          cache: true\n\n      - uses: azure/setup-helm@v4\n        with:\n          version: v3.11.0\n\n      - name: Install Helm Compose\n        run: make install\n\n      - uses: helm/kind-action@v1.10.0\n      \n      - name: Run Helm Compose\n        run: helm compose up -f examples/simple-compose.yaml\n\n"
  },
  {
    "path": ".github/workflows/dependabot-automerge.yaml",
    "content": "name: Dependabot auto-approve\non: pull_request\n\npermissions:\n  pull-requests: write\n\njobs:\n  dependabot:\n    runs-on: ubuntu-latest\n    if: github.actor == 'dependabot[bot]'\n    steps:\n      - name: Dependabot metadata\n        id: metadata\n        uses: dependabot/fetch-metadata@v2\n        with:\n          github-token: \"${{ secrets.GITHUB_TOKEN }}\"\n\n      - name: Approve PR\n        run: gh pr review --approve \"$PR_URL\"\n        env:\n          PR_URL: ${{github.event.pull_request.html_url}}\n          GH_TOKEN: ${{secrets.GITHUB_TOKEN}}\n\n      - name: Auto-merge PR\n        run: gh pr merge --auto --merge \"$PR_URL\"\n        env:\n          PR_URL: ${{github.event.pull_request.html_url}}\n          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}"
  },
  {
    "path": ".github/workflows/docs.yaml",
    "content": "name: Deploy docs\non:\n  push:\n    branches:\n      - main\n    paths:\n      - docs/**\n      - mkdocs.yaml\n  workflow_dispatch:\npermissions:\n  contents: write\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    if: github.event.repository.fork == false\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          fetch-tags: true\n\n      - uses: actions/setup-python@v5\n        with:\n          python-version: 3.x\n\n      - name: Run generate cache key\n        run: echo \"cache_id=$(date --utc '+%V')\" >> $GITHUB_ENV\n\n      - uses: actions/cache@v4\n        with:\n          key: mkdocs-cache-${{ env.cache_id }}\n          path: .cache\n          restore-keys: |\n            mkdocs-\n\n      - name: Run setup mkdocs dependencies\n        run: pip install mkdocs mkdocs-material mkdocs-autolinks-plugin mkdocs-drawio-file mkdocs-git-revision-date-localized-plugin fontawesome_markdown mike pymdown-extensions\n\n      - name: Run mkdocs deployment\n        run: |\n          git config --global user.name \"github-actions[bot]\"\n          git config --global user.email \"41898282+github-actions[bot]@users.noreply.github.com\"\n          mike deploy -b gh-pages -p -F mkdocs.yaml -u next\n\n      - name: Run mkdocs release deployment\n        if: \"contains(github.event.head_commit.message, 'docs: release')\"\n        run: |\n          git config --global user.name \"github-actions[bot]\"\n          git config --global user.email \"41898282+github-actions[bot]@users.noreply.github.com\"\n\n          LATEST_TAG=$(git describe --abbrev=0)\n          SHORT_VERSION=${LATEST_TAG%.*}\n\n          mike deploy -b gh-pages -p -F mkdocs.yaml -u ${SHORT_VERSION} latest\n\n"
  },
  {
    "path": ".github/workflows/release.yaml",
    "content": "name: Create Release\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: 'Version number of the new release'\n        required: true\n        type: string\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  release:\n    name: release\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          fetch-tags: true\n\n      - name: Update and create tag\n        run: |\n          # Setup git\n          git config --global user.name \"github-actions[bot]\"\n          git config --global user.email \"41898282+github-actions[bot]@users.noreply.github.com\"\n\n          # Update version in documentation and helm plugin config\n          sed -i 's\\--version .*\\--version ${{ inputs.version }}\\g' docs/quick-start.md\n          sed -i 's\\--version .*\\--version ${{ inputs.version }}\\g' README.md\n          sed -i 's\\^version:.*\\version: ${{ inputs.version }}\\g' plugin.yaml\n\n          # Update changelog\n          sed -i 's\\# Changes since .*\\# ${{ inputs.version }}\\g' CHANGELOG.md\n          echo -e \"# Changes since ${{ inputs.version }}\\n$(cat CHANGELOG.md)\" > CHANGELOG.md\n\n          # Commit, tag and push\n          git commit -am \"docs: release ${{ inputs.version }}\"\n          git tag ${{ inputs.version }} -am \"${{ inputs.version }}\"\n          git push --follow-tags \n\n      - name: Create release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          TAG: ${{ inputs.version }}\n        run: |\n          gh release create \"${TAG}\" \\\n              --title=\"${TAG}\" \\\n              --generate-notes \\\n              --prerelease\n"
  },
  {
    "path": ".gitignore",
    "content": ".vscode\n.hcstate\n\nvendor/\nbin/\nbuild/\nrelease/\n\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Dependency directories (remove the comment below to include it)\n# vendor/\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changes since 1.3.0\n# 1.3.0\n- feat: add templating command\n- chore: upgrade to golang 1.22\n\n# 1.2.0\n- feat: add wait option\n- feat: apiVersion 1.1 for wait option and add better version handling\n- fix: stop creation of revisions if the helm compose file didn't change\n\n# 1.1.2\n- chore: dependency upgrades\n\n# 1.1.1\n- bugfix: when the target bucket is empty no state files are written\n\n# 1.1.0\n- feat: add support for s3 as a revision storage provider / backend\n- chore: upgrade dependencies to the latest versions\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright © 2023 The Helm Compose Authors\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "LICENSES/helm/LICENSE",
    "content": "=== https://github.com/helm/helm ===\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2016 The Kubernetes Authors All Rights Reserved\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "LICENSES/helm-diff/LICENSE",
    "content": "=== https://github.com/databus23/helm-diff ===\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "LICENSES/helm-template/LICENSE",
    "content": "=== https://github.com/technosophos/helm-template ===\n\nHelm Template Plugin\nCopyright (C) 2016, Matt Butcher\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "Makefile",
    "content": "HELM_HOME := $(shell bash -c 'eval $$(helm env); echo $$HELM_PLUGINS')\nLDFLAGS := -s -w\n\n.PHONY: install\ninstall: build\n\tmkdir -p $(HELM_HOME)/helm-compose/bin\n\tcp bin/compose $(HELM_HOME)/helm-compose/bin\n\tcp plugin.yaml $(HELM_HOME)/helm-compose/\n\n.PHONY: build\nbuild:\n\tmkdir -p bin/\n\tgo build -v -o bin/compose\n\n.PHONY: dist\ndist: export COPYFILE_DISABLE=1 #teach OSX tar to not put ._* files in tar archive\ndist: export CGO_ENABLED=0\ndist:\n\trm -rf build/compose/* release/*\n\tmkdir -p build/compose/bin release/\n\tcp README.md LICENSE plugin.yaml build/compose\n\tGOOS=linux GOARCH=amd64 go build -o build/compose/bin/compose -trimpath -ldflags=\"$(LDFLAGS)\"\n\ttar -C build/ -zcvf $(CURDIR)/release/helm-compose-linux-amd64.tgz compose/\n\tGOOS=linux GOARCH=arm64 go build -o build/compose/bin/compose -trimpath -ldflags=\"$(LDFLAGS)\"\n\ttar -C build/ -zcvf $(CURDIR)/release/helm-compose-linux-arm64.tgz compose/\n\tGOOS=freebsd GOARCH=amd64 go build -o build/compose/bin/compose -trimpath -ldflags=\"$(LDFLAGS)\"\n\ttar -C build/ -zcvf $(CURDIR)/release/helm-compose-freebsd-amd64.tgz compose/\n\tGOOS=darwin GOARCH=amd64 go build -o build/compose/bin/compose -trimpath -ldflags=\"$(LDFLAGS)\"\n\ttar -C build/ -zcvf $(CURDIR)/release/helm-compose-macos-amd64.tgz compose/\n\tGOOS=darwin GOARCH=arm64 go build -o build/compose/bin/compose -trimpath -ldflags=\"$(LDFLAGS)\"\n\ttar -C build/ -zcvf $(CURDIR)/release/helm-compose-macos-arm64.tgz compose/\n\trm build/compose/bin/compose\n\tGOOS=windows GOARCH=amd64 go build -o build/compose/bin/compose.exe -trimpath -ldflags=\"$(LDFLAGS)\"\n\ttar -C build/ -zcvf $(CURDIR)/release/helm-compose-windows-amd64.tgz compose/"
  },
  {
    "path": "README.md",
    "content": "# ⚠️ Project Discontinued\n\nThis open-source project is **no longer actively maintained**.\n\n- No new features or bug fixes will be added.\n- Pull requests and issues may not receive responses.\n\n---\n\n![helm-compose-banner](https://user-images.githubusercontent.com/18513179/240495789-e76890d3-f0f9-48b9-9d18-89e53effe65b.png)\r\n\r\n[![Build Status](https://github.com/seacrew/helm-compose/actions/workflows/build.yaml/badge.svg)](https://github.com/seacrew/helm-compose/actions/workflows/build.yaml)\r\n[![Go Report Card](https://goreportcard.com/badge/github.com/seacrew/helm-compose)](https://goreportcard.com/report/github.com/seacrew/helm-compose)\r\n[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=seacrew_helm-compose&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=seacrew_helm-compose)\r\n[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=seacrew_helm-compose&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=seacrew_helm-compose)\r\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/seacrew/helm-compose)](https://github.com/seacrew/helm-compose/releases/latest)\r\n\r\nHelm Compose is a tool for managing multiple releases of one or many different Helm charts. It is heavily inspired by Docker Compose and is an extension of the package manager idea behind Helm itself. It allows for full configuration-as-code capabilities in an single yaml file.\n\r\n## Installation\r\n\r\nIt is requirement to use helm v3.10.0+. \r\n\r\nInstall a specific version of helm compose (recommended). Click [here](https://github.com/seacrew/helm-compose/releases/latest) for the latest version.\r\n\r\n```\r\nhelm plugin install https://github.com/seacrew/helm-compose --version 1.3.0\n```\r\n\r\nInstall the latest version.\r\n\r\n```\r\nhelm plugin install https://github.com/seacrew/helm-compose\r\n```\r\n\r\n## Quick Start Guide\r\n\r\nHelm Compose makes it easy to define a list of Releases and all necessary Repositories for the charts you use in a single compose file.\r\n\r\nInstall your releases:\r\n\r\n```bash\r\n$ helm compose up -f helm-compose.yaml\r\n```\r\n\r\nUninstall your releases\r\n\r\n```bash\r\n$ helm compose down -f helm-compose.yaml\r\n```\r\n\r\nA Helm Compose file looks something like this:\r\n\r\n```yaml\r\napiVersion: 1.1\r\n\r\nstorage:\r\n  name: mycompose\r\n  type: local # default\r\n  path: .hcstate # default\r\n\r\nreleases:\r\n  wordpress:\r\n    chart: bitnami/wordpress\r\n    chartVersion: 14.3.2\r\n  wordpress2:\r\n    chart: bitnami/wordpress\r\n    chartVersion: 15.2.22\r\n    namespace: homepage\r\n    createNamespace: true\r\n  postgres:\r\n    chart: bitnami/postgresql\r\n    chartVersion: 12.1.9\r\n    namespace: database\r\n    createNamespace: true\r\n\r\nrepositories:\r\n  bitnami: https://charts.bitnami.com/bitnami\r\n```\r\n\r\nCheck out the [examples](https://github.com/seacrew/helm-compose/tree/main/examples) directory.\r\n\r\n## Documentation\r\n\r\nCheckout the complete [documentation.](https://seacrew.github.io/helm-compose/)\r\n"
  },
  {
    "path": "cmd/down.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage cmd\n\nimport (\n\t\"github.com/seacrew/helm-compose/internal/compose\"\n\t\"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/spf13/cobra\"\n)\n\n// downCmd represents the down command\nvar downCmd = &cobra.Command{\n\tUse:   \"down\",\n\tShort: \"This command uninstalls all releases defined in your compose file.\",\n\tLong:  ``,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tcmd.SilenceUsage = true\n\n\t\tif err := compose.CompatibleHelmVersion(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tconfig, err := config.ParseComposeFile(composeFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn compose.RunDown(config)\n\t},\n}\n\nfunc init() {\n\trootCmd.AddCommand(downCmd)\n}\n"
  },
  {
    "path": "cmd/get.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage cmd\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/seacrew/helm-compose/internal/compose\"\n\t\"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar getCmd = &cobra.Command{\n\tUse:   \"get [revision]\",\n\tShort: \"This command retrieves the decoded content from the revision id you specify.\",\n\tLong:  ``,\n\tArgs:  cobra.ExactArgs(1),\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tcmd.SilenceUsage = true\n\n\t\tif err := compose.CompatibleHelmVersion(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tconfig, err := config.ParseComposeFile(composeFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\trevision, err := strconv.Atoi(args[0])\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"REVISION must be a number\")\n\t\t}\n\n\t\tif revision < 1 {\n\t\t\treturn fmt.Errorf(\"REVISION must be a positiv number\")\n\t\t}\n\n\t\treturn compose.GetRevision(revision, config)\n\t},\n}\n\nfunc init() {\n\trootCmd.AddCommand(getCmd)\n}\n"
  },
  {
    "path": "cmd/list.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage cmd\n\nimport (\n\t\"github.com/seacrew/helm-compose/internal/compose\"\n\t\"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar listCmd = &cobra.Command{\n\tUse:   \"list\",\n\tShort: \"This command lists the revisions ids for your compose file.\",\n\tLong:  ``,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tcmd.SilenceUsage = true\n\n\t\tif err := compose.CompatibleHelmVersion(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tconfig, err := config.ParseComposeFile(composeFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn compose.ListRevisions(config)\n\t},\n}\n\nfunc init() {\n\trootCmd.AddCommand(listCmd)\n}\n"
  },
  {
    "path": "cmd/root.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage cmd\n\nimport (\n\t\"os\"\n\n\t\"github.com/spf13/cobra\"\n)\n\n// upCmd represents the up command\nvar composeFile string\n\n// rootCmd represents the base command when called without any subcommands\nvar rootCmd = &cobra.Command{\n\tUse:   \"compose\",\n\tShort: \"Compose is a helm plugin to define and manage multiple helm releases as a single entity.\",\n\tLong: `With the Helm Compose plugin you are able to create a single compose file\nto manage a multitude of releases. Either for deploying one chart multiple times in\nthe same or different namespaces or to deploy multiple charts as a single entity together.\n\nThis idea is heavily inspired and influenced by the idea behind docker-compose.`,\n}\n\nfunc Execute() {\n\terr := rootCmd.Execute()\n\tif err != nil {\n\t\tos.Exit(1)\n\t}\n}\n\nfunc init() {\n\trootCmd.PersistentFlags().StringVarP(&composeFile, \"file\", \"f\", \"\", \"Compose configuration file\")\n}\n"
  },
  {
    "path": "cmd/template.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage cmd\n\nimport (\n\t\"github.com/seacrew/helm-compose/internal/compose\"\n\t\"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar templateCmd = &cobra.Command{\n\tUse:   \"template [RELEASE ...]\",\n\tShort: \"Render templates for all releases locally and display the output.\",\n\tLong:  ``,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tcmd.SilenceUsage = true\n\n\t\tif err := compose.CompatibleHelmVersion(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tconfig, err := config.ParseComposeFile(composeFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn compose.Template(config, args)\n\t},\n}\n\nfunc init() {\n\trootCmd.AddCommand(templateCmd)\n}\n"
  },
  {
    "path": "cmd/up.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage cmd\n\nimport (\n\t\"github.com/seacrew/helm-compose/internal/compose\"\n\t\"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar upCmd = &cobra.Command{\n\tUse:   \"up\",\n\tShort: \"This command installs or upgrades all the releases defined in your compose file and uninstalls releases that have been removed since the last revision.\",\n\tLong:  ``,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tcmd.SilenceUsage = true\n\n\t\tif err := compose.CompatibleHelmVersion(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tconfig, err := config.ParseComposeFile(composeFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn compose.RunUp(config)\n\t},\n}\n\nfunc init() {\n\trootCmd.AddCommand(upCmd)\n}\n"
  },
  {
    "path": "docs/commands/down.md",
    "content": "# helm compose down\n\nUninstall all releases defined in your `helm-compose.yaml`\n\n## Usage\n\nThe following command will uninstall all releases of the previous revision if one exists. Otherwise the releases defined in your current `helm-compose.yaml` will be uninstalled.\n\n```\nhelm compose down [flags]\n```\n\n## Options\n\n```\nFlags:\n  -h, --help   help for down\n\nGlobal Flags:\n  -f, --file string   Compose configuration file\n```\n"
  },
  {
    "path": "docs/commands/get.md",
    "content": "# helm compose get\n\nGet a previous revision of your `helm-compose.yaml`\n\n## Usage\n\nThe following command will return the previous `helm-compose.yaml` content on stdout.\n\n```\nhelm compose get [revision] [flags]\n```\n\n## Options\n\n```\nFlags:\n  -h, --help   help for get\n\nGlobal Flags:\n  -f, --file string   Compose configuration file\n```\n"
  },
  {
    "path": "docs/commands/list.md",
    "content": "# helm compose list\n\nList previous revisions of your `helm-compose.yaml`\n\n## Usage\n\n```\nhelm compose list [flags]\n```\n\n## Options\n\n```\nFlags:\n  -h, --help   help for list\n\nGlobal Flags:\n  -f, --file string   Compose configuration file\n```\n\n## Example\n\n```\n$ helm compose list\n\n| Date             | Revision |\n| ---------------- | -------- |\n| 2023-05-22 10:24 |        1 |\n| 2023-05-22 11:19 |        2 |\n```\n"
  },
  {
    "path": "docs/commands/template.md",
    "content": "# helm compose template\n\nTemplate all kubernetes resources for the releases specified in your `helm-compose.yaml` and print them out to stdout.\n\n## Usage\n\nThe following command will print out all kubernetes resources that would be installed or upgraded on stdout.\n\n```\nhelm compose template [releases...] [flags]\n```\n\n## Options\n\n```\nFlags:\n  -h, --help   help for template\n\nGlobal Flags:\n  -f, --file string   Compose configuration file\n```\n"
  },
  {
    "path": "docs/commands/up.md",
    "content": "# helm compose up\n\nInstall all releases and repositories defined in your `helm-compose.yaml`\n\n## Usage\n\nThe following command will install all releases defined in your `helm-compose.yaml` and will compare it to the latest previous revision and uninstall all releases that have been removed since then.\n\n```\nhelm compose up [flags]\n```\n\n## Options\n\n```\nFlags:\n  -h, --help   help for up\n\nGlobal Flags:\n  -f, --file string   Compose configuration file\n```\n"
  },
  {
    "path": "docs/compose-file-reference.md",
    "content": "# Compose File Reference\n\n## storage\n\n```yaml\nstorage:\n  name: my-compose\n  type: local\n  numberOfRevisions: 10\n```\n\n| Option            | Type   | Description                                                                                 | Required | Default | ApiVersion |\n| ----------------- | ------ | ------------------------------------------------------------------------------------------- | -------- | ------- | ---------- |\n| name              | string | Name to be used to store revisions with a storage provider.                                 | true     |         | 1.0        |\n| type              | string | Type / name of the storage provider you want to use. By default local files will be stored. | false    | local   | 1.0        |\n| numberOfRevisions | int    | Number of revisions to be stored and to be able to rollback to.                             | false    | 10      | 1.0        |\n\nMore details regarding the available storage providers and provider specific options can be found [here.](storage-providers.md)\n\n## releases\n\n```yaml\nreleases:\n  my-website:\n    chart: bitnami/wordpress\n```\n\n| Option           | Type   | Description                                                                                                                                                                 | Required | Default        | ApiVersion |\n| ---------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------- | ---------- |\n| chart            | string | Name of the chart to be used.                                                                                                                                               | true     |                | 1.0        |\n| chartVersion     | string | Version of the chart to be used.                                                                                                                                            | false    | latest         | 1.0        |\n| forceUpdate      | bool   | Force resource updates through a replacement strategy                                                                                                                       | false    | false          | 1.0        |\n| historyMax       | int    | Limit the maximum number of revisions saved per release.                                                                                                                    | false    | 10             | 1.0        |\n| createNamespace  | bool   | Create the release namespace if not present                                                                                                                                 | false    | false          | 1.0        |\n| cleanUpOnFail    | bool   | Allow deletion of new resources created in this upgrade when upgrade fails.                                                                                                 | false    | false          | 1.0        |\n| dependencyUpdate | bool   | Update dependencies if they are missing before installing the chart                                                                                                         | false    | false          | 1.0        |\n| skipTlsVerify    | bool   | Skip tls certificate checks for the chart download                                                                                                                          | false    | false          | 1.0        |\n| skipCrds         | bool   | If set, no CRDs will be installed.                                                                                                                                          | false    | false          | 1.0        |\n| postRenderer     | string | The path to an executable to be used for post rendering. If it exists in $PATH, the binary will be used, otherwise it will try to look for the executable at the given path | false    |                | 1.0        |\n| postRendererArgs | array  | An argument to the post-renderer (can specify multiple) (default [])                                                                                                        | false    |                | 1.0        |\n| kubeconfig       | string | Path to the kubeconfig file                                                                                                                                                 | false    | ~/.kube/config | 1.0        |\n| kubecontext      | string | Name of the kubeconfig context to use                                                                                                                                       | false    |                | 1.0        |\n| caFile           | string | Verify certificates of HTTPS-enabled servers using this CA bundle                                                                                                           | false    |                | 1.0        |\n| certFile         | string | Identify HTTPS client using this SSL certificate file                                                                                                                       | false    |                | 1.0        |\n| keyFile          | string | Identify HTTPS client using this SSL key file                                                                                                                               | false    |                | 1.0        |\n| timeout          | string | Time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s)                                                                                   | false    | 5m             | 1.0        |\n| wait             | bool   | Waits until all Pods are in a ready state,  It will wait for as long as the --timeout value                                                                                 | false    |                | 1.1        |\n| values           | map    | Map of values with highest priority to overwrite any values in the chart values or your additional values files. (Allows for usage of environment variables.)               | false    |                | 1.0        |\n| valueFiles       | string | List of paths to value files.                                                                                                                                               | false    | 5m             | 1.0        |\n\nUninstall options:\n\n| Option           | Type   | Description                                                                                                  | Required | Default    | ApiVersion |\n| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------ | -------- | ---------- | ---------- |\n| deletionStrategy | string | Must be \"background\", \"orphan\", or \"foreground\". Selects the deletion cascading strategy for the dependents. | false    | background | 1.0        |\n| deletionTimeout  | string | Time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s)                    | false    | 5m         | 1.0        |\n| deletionNoHooks  | bool   | Prevent hooks from running during uninstallation                                                             | false    | false      | 1.0        |\n| keepHistory      | bool   | Remove all associated resources and mark the release as deleted, but retain the release history              | false    | false      | 1.0        |\n\n## repositories\n\nA map of repository names and their respective urls.\n\n```yaml\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n```\n"
  },
  {
    "path": "docs/index.md",
    "content": "![helm-compose-banner](https://user-images.githubusercontent.com/18513179/212496531-1d166236-ed88-411d-8403-ad1f94d28846.png)\n\n[![Build Status](https://github.com/seacrew/helm-compose/actions/workflows/build.yaml/badge.svg)](https://github.com/seacrew/helm-compose/actions/workflows/build.yaml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/seacrew/helm-compose)](https://goreportcard.com/report/github.com/seacrew/helm-compose)\n[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=seacrew_helm-compose&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=seacrew_helm-compose)\n[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=seacrew_helm-compose&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=seacrew_helm-compose)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/seacrew/helm-compose)](https://github.com/seacrew/helm-compose/releases/latest)\n\nHelm Compose is a tool for managing multiple releases for one or many different Helm charts. It is an extension of the package manager idea behind Helm and is heavily inspired by Docker Compose.\n"
  },
  {
    "path": "docs/key-features-and-use-cases.md",
    "content": "# Key Features and Use Cases\n\nThe main idea behind `helm-compose` is to control / configure all helm related options as code by providing a compose file structure to configure everything you need to setup your helm based infrastructure.\n\n## Repository handling\n\nConfiguration based installation of all necessary repositories you define as a dependency in your `helm-compose.yaml` before triggering the installation of your releases.\n\n```yaml\napiVersion: 1.1\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n```\n\n## Multi release handling\n\nThe main feature of `helm-compose` is the ability to define a multitude of releases inside a single file. `helm-compose` supports single kubernetes-cluster and multi-cluster configuration.\n\n### Single cluster\n\nDefine as many releases as you would like for one or more namespaces.\n\n```yaml\napiVersion: 1.1\n\nreleases:\n  wordpress:\n    chart: bitnami/wordpress\n    chartVersion: 14.3.2\n    namespace: homepage\n  wordpress2:\n    chart: bitnami/wordpress\n    chartVersion: 15.2.22\n    namespace: homepage\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n```\n\n### Multi cluster\n\nYou can either use the `kubeconfig` options to point to a different path and use the `kubecontext` to select a specific context inside your kubeconfig.\n\n```yaml\napiVersion: 1.1\n\nreleases:\n  wordpress-dev:\n    chart: bitnami/wordpress\n    chartVersion: 14.3.2\n    namespace: homepage\n    kubeconfig: ~/.kube/dev\n  wordpress-int:\n    chart: bitnami/wordpress\n    chartVersion: 15.2.22\n    namespace: homepage\n    kubeconfig: ~/.kube/int\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n```\n\n### Environment variables\n\n`helm-compose` is able to inject environment variables inside your values block to deal with secrets that shouldn't be committed to your source control.\n\nSyntax: `${MY_ENV_VARIABLE}`.\n\n```bash\nexport WORDPRESS_ADMIN_PASSWORD=\"xxx\"\nexport MARIADB_ROOT_PASSWORD=\"xxx\"\nhelm compose up\n```\n\n```yaml\napiVersion: 1.1\n\nreleases:\n  wordpress:\n    chart: bitnami/wordpress\n    values:\n      wordpressPassword: ${WORDPRESS_ADMIN_PASSWORD}\n      mariadb.auth.rootPassword: ${MARIADB_ROOT_PASSWORD}\n```\n\n## Revision handling\n\nRevisions are essentially snapshots of your current `helm-compose.yaml`. Every time you trigger `helm compose up` a new revision will be created and stored (By default the last 10 revisions are kept).\n\n### Configuration\n\n```yaml\napiVersion: 1.1\n\nstorage:\n  name: wordpress\n  type: local # default: local\n  numberOfRevisions: 5 # default: 10\n```\n\n### Usage\n\nYou can list your revisions and get the content of your previous revisions via the [`helm compose list`](commands/list.md) and [`helm compose get`](commands/get.md) commands.\n\n### Rollback\n\nJust select a revision you want to go back to. You can check the content with the `helm compose get` command and parse it directly into any `helm compose` command like so:\n\n```bash\n$ helm compose list\n| Date             | Revision |\n| ---------------- | -------- |\n| 2023-05-24 23:56 |       12 |\n| 2023-05-24 23:56 |       13 |\n| 2023-05-24 23:57 |       14 |\n| 2023-05-24 23:57 |       15 |\n| 2023-05-24 23:57 |       16 |\n\n# select revision 15 and use the pipe | operator to parse the content back into compose up with -f -\nhelm compose get 15 | helm compose up -f -\n```\n"
  },
  {
    "path": "docs/quick-start.md",
    "content": "# Quick Start\n\n## Installation\n\nInstall a specific version (recommended). Click [here](https://github.com/seacrew/helm-compose/releases/latest) for the latest version.\n\n```\nhelm plugin install https://github.com/seacrew/helm-compose --version 1.3.0\n```\n\nInstall latest version.\n\n```\nhelm plugin install https://github.com/seacrew/helm-compose\n```\n\n## How to use helm compose\n\nHelm Compose makes it easy to define a Compose file containing a list of Releases and necessary Repositories for the charts you use.\n\nInstall your releases:\n\n```\nhelm compose up -f helm-compose.yaml\n```\n\nUninstall your releases\n\n```\nhelm compose down -f helm-compose.yaml\n```\n\nA Helm Compose file looks something like this:\n\n```yaml\napiVersion: 1.1\n\nstorage:\n  name: mycompose\n  type: local # default\n  path: .hcstate # default\n\nreleases:\n  wordpress:\n    chart: bitnami/wordpress\n    chartVersion: 14.3.2\n  wordpress2:\n    chart: bitnami/wordpress\n    chartVersion: 15.2.22\n    namespace: homepage\n    createNamespace: true\n  postgres:\n    chart: bitnami/postgresql\n    chartVersion: 12.1.9\n    namespace: database\n    createNamespace: true\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n```\n\nAll `helm-compose` commands accept the `-f` flag to pass your compose file location. Otherwise `helm-compose` will automatically look for a list of file names inside your current directory:\n\n- helm-compose.yaml\n- helm-compose.yml\n- helmcompose.yaml\n- helm-compose.yml\n- helmcompose.yaml\n- helmcompose.yml\n- helmcompose\n- compose.yaml\n- compose.yml\n\nCheck out the [helm compose examples](https://github.com/seacrew/helm-compose/tree/main/examples).\n"
  },
  {
    "path": "docs/storage-providers.md",
    "content": "# Storage Providers\n\nFollowing options are applicable regardless of the selected provider.\n\n| Option            | Type   | Description                                                                                 | Required | Default | ApiVersion |\n| ----------------- | ------ | ------------------------------------------------------------------------------------------- | -------- | ------- | ---------- |\n| name              | string | Name to be used to store revisions with a storage provider.                                 | true     |         | 1.0        |\n| type              | string | Type / name of the storage provider you want to use. By default local files will be stored. | false    | local   | 1.0        |\n| numberOfRevisions | int    | Number of revisions to be stored and to be able to rollback to.                             | false    | 10      | 1.0        |\n\n## Local\n\nStores your compose revisions locally inside the `.hcstate` directory next to your `helm-compose.yaml`.\n\n| Option | Type   | Description                                                                                           | Required | Default  | ApiVersion |\n| ------ | ------ | ----------------------------------------------------------------------------------------------------- | -------- | -------- | ---------- |\n| path   | string | The directory path to store your revisions (Relative to the directory you execute `helm compose` in). | false    | .hcstate | 1.0        |\n\n## Kubernetes\n\nStores your compose revisions similar to helm releases inside secrets in a kubernetes cluster namespace.\n\n| Option      | Type   | Description                                        | Required | Default         | ApiVersion |\n| ----------- | ------ | -------------------------------------------------- | -------- | --------------- | ---------- |\n| namespace   | string | The namespace to store your revisions in.          | false    | default         | 1.0        |\n| kubeconfig  | string | The path to your kubeconfig file                   | false    | ~/.kube/config  | 1.0        |\n| kubecontext | string | The context to use from your specified kubeconfig. | false    | current-context | 1.0        |\n\n## S3\n\nStores your compose revisions inside a s3 bucket. You will need to set your AWS credentials (access and secret key) via [environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) or the `~/.aws/config` file. [Official AWS documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html).\n\n\n| Option           | Type   | Description                                                                                                | Required | Default                                                                      | ApiVersion |\n| ---------------- | ------ | ---------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------- | ---------- |\n| s3bucket         | string | Specify the bucket name to upload to and download from.                                                    | true     |                                                                              | 1.0        |\n| s3prefix         | string | Specify the object prefix (directory) for the revisions to be uploaded to and downloaded from.             | false    | (root path)                                                                  | 1.0        |\n| s3region         | string | Set a custom S3 region.                                                                                    | false    | By default the region will be read from the AWS_REGION environment variable. | 1.0        |\n| s3endpoint       | string | Set a custom S3 endpoint / host url.                                                                       | false    | Default AWS S3 service endpoint.                                             | 1.0        |\n| s3insecure       | bool   | Disable the verification of the servers certificate chain and hostname.                                    | false    | false                                                                        | 1.0        |\n| s3disableSSL     | bool   | Disable the usage of SSL / https.                                                                          | false    | false                                                                        | 1.0        |\n| s3forcePathStyle | bool   | Enforce to use path style. Especially useful for none AWS S3 provider which often only support path style. | false    | false                                                                        | 1.0        |\n\n## GCS\n\nNot yet implemented\n"
  },
  {
    "path": "docs/stylesheets/extra.css",
    "content": ":root {\n  --md-primary-fg-color:        #00acc1;\n}"
  },
  {
    "path": "examples/.gitignore",
    "content": ".hcstate\n.override"
  },
  {
    "path": "examples/k8s-storage-compose.yaml",
    "content": "apiVersion: 1.1\n\nstorage:\n  name: k8s-test\n  type: kubernetes\n  numberOfRevisions: 5\n\nreleases:\n  k8s-nginx:\n    chart: bitnami/nginx\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n"
  },
  {
    "path": "examples/local-storage-compose.yaml",
    "content": "apiVersion: 1.1\n\nstorage:\n  name: local\n  type: local\n  path: .override\n\nreleases:\n  default:\n    chart: bitnami/nginx\n    chartVersion: 14.2.1\n    wait: true\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n"
  },
  {
    "path": "examples/s3-storage-compose.yaml",
    "content": "apiVersion: 1.1\n\nstorage:\n  name: s3-test\n  type: s3\n  s3bucket: helm-compose\n  s3region: eu-central-1\n  s3prefix: wordpress\n\nreleases:\n  wordpress:\n    chart: bitnami/wordpress\n    chartVersion: 14.3.2\n    namespace: wordpress\n    createNamespace: true\n    valueFiles:\n      - ./values/wordpress.yaml\n    values:\n      wordpressBlogName: Awesome Site\n      wordpressPassword: \"${WORDPRESS_PASSWORD}}\"\n      mariadb.auth:\n        rootPassword: \"${MARIADB_ROOT_PASSWORD}}\"\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n"
  },
  {
    "path": "examples/simple-compose.yaml",
    "content": "apiVersion: 1.1\n\nstorage:\n  name: simple\n  type: local\n\nreleases:\n  default:\n    chart: bitnami/nginx\n    chartVersion: 14.2.1\n  jekyll:\n    chart: bitnami/nginx\n    chartVersion: 14.2.1\n    values:\n      cloneStaticSiteFromGit:\n        enabled: true\n        repository: https://github.com/jekyll/jekyll\n        branch: gh-pages\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n"
  },
  {
    "path": "examples/values/wordpress.yaml",
    "content": "wordpressUsername: user\nwordpressEmail: user@example.com\nallowEmptyPassword: false\nmariadb:\n  primary:\n    persistence:\n      enabled: false\npersistence:\n  enabled: false\n"
  },
  {
    "path": "examples/wordpress-compose.yaml",
    "content": "apiVersion: 1.1\n\nstorage:\n  name: wordpress\n  type: local\n\nreleases:\n  site1:\n    chart: bitnami/wordpress\n    chartVersion: 14.3.2\n    namespace: site1\n    createNamespace: true\n    valueFiles:\n      - ./values/wordpress.yaml\n    values:\n      wordpressBlogName: Awesome Site\n      wordpressPassword: awesome\n      mariadb.auth:\n        rootPassword: \"awesome-password\"\n  site2:\n    chart: bitnami/wordpress\n    chartVersion: 14.3.2\n    namespace: site2\n    createNamespace: true\n    valueFiles:\n      - ./values/wordpress.yaml\n    values:\n      wordpressBlogName: Super Awesome Site\n      wordpressPassword: super-awesome\n      mariadb.auth:\n        rootPassword: \"super-awesome-password\"\n\nrepositories:\n  bitnami: https://charts.bitnami.com/bitnami\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/seacrew/helm-compose\n\ngo 1.22.0\n\ntoolchain go1.22.2\n\nrequire (\n\tgithub.com/Masterminds/semver v1.5.0\n\tgithub.com/aws/aws-sdk-go v1.53.7\n\tgithub.com/jwalton/go-supportscolor v1.2.0\n\tgithub.com/spf13/cobra v1.8.0\n\tgithub.com/stretchr/testify v1.9.0\n\tgopkg.in/yaml.v2 v2.4.0\n\tk8s.io/apimachinery v0.30.1\n\tk8s.io/client-go v0.30.1\n)\n\nrequire (\n\tgithub.com/google/gnostic-models v0.6.8 // indirect\n\tgithub.com/jmespath/go-jmespath v0.4.0 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n)\n\nrequire (\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.12.0 // indirect\n\tgithub.com/go-logr/logr v1.4.2 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.21.0 // indirect\n\tgithub.com/go-openapi/jsonreference v0.21.0 // indirect\n\tgithub.com/go-openapi/swag v0.23.0 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/golang/protobuf v1.5.4 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/imdario/mergo v0.3.16 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/mailru/easyjson v0.7.7 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgolang.org/x/net v0.25.0 // indirect\n\tgolang.org/x/oauth2 v0.20.0 // indirect\n\tgolang.org/x/sys v0.20.0 // indirect\n\tgolang.org/x/term v0.20.0 // indirect\n\tgolang.org/x/text v0.15.0 // indirect\n\tgolang.org/x/time v0.5.0 // indirect\n\tgoogle.golang.org/protobuf v1.34.1 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tk8s.io/api v0.30.1\n\tk8s.io/klog/v2 v2.120.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a // indirect\n\tk8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect\n\tsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect\n\tsigs.k8s.io/yaml v1.4.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=\ngithub.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=\ngithub.com/aws/aws-sdk-go v1.53.5 h1:1OcVWMjGlwt7EU5OWmmEEXqaYfmX581EK317QJZXItM=\ngithub.com/aws/aws-sdk-go v1.53.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=\ngithub.com/aws/aws-sdk-go v1.53.7 h1:ZSsRYHLRxsbO2rJR2oPMz0SUkJLnBkN+1meT95B6Ixs=\ngithub.com/aws/aws-sdk-go v1.53.7/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=\ngithub.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=\ngithub.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=\ngithub.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=\ngithub.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=\ngithub.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=\ngithub.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=\ngithub.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=\ngithub.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=\ngithub.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=\ngithub.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=\ngithub.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=\ngithub.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=\ngithub.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=\ngithub.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=\ngithub.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=\ngithub.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/jwalton/go-supportscolor v1.2.0 h1:g6Ha4u7Vm3LIsQ5wmeBpS4gazu0UP1DRDE8y6bre4H8=\ngithub.com/jwalton/go-supportscolor v1.2.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=\ngithub.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=\ngithub.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g=\ngithub.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE=\ngithub.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk=\ngithub.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=\ngithub.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=\ngithub.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=\ngithub.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=\ngolang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=\ngolang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=\ngolang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=\ngolang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=\ngolang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=\ngolang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=\ngolang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=\ngolang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=\ngolang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=\ngolang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=\ngolang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=\ngolang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=\ngolang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=\ngolang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=\ngolang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=\ngolang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=\ngoogle.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=\ngoogle.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=\ngoogle.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nk8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY=\nk8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM=\nk8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U=\nk8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=\nk8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q=\nk8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc=\nk8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=\nk8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3 h1:SbdLaI6mM6ffDSJCadEaD4IkuPzepLDGlkd2xV0t1uA=\nk8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=\nk8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a h1:zD1uj3Jf+mD4zmA7W+goE5TxDkI7OGJjBNBzq5fJtLA=\nk8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc=\nk8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY=\nk8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nk8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=\nk8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=\nsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=\nsigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=\nsigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=\nsigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=\nsigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=\n"
  },
  {
    "path": "internal/compose/compose.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage compose\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n\tprov \"github.com/seacrew/helm-compose/internal/provider\"\n\t\"github.com/seacrew/helm-compose/internal/util\"\n)\n\nfunc RunUp(config *cfg.Config) error {\n\tfor name, url := range config.Repositories {\n\t\tif err := addHelmRepository(name, url); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tpreviousConfig, err := prov.Load(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !config.Equal(previousConfig) {\n\t\tif err := prov.Store(config); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tvar wg sync.WaitGroup\n\n\tfor name, release := range config.Releases {\n\t\twg.Add(1)\n\t\tgo func(name string, release cfg.Release) {\n\t\t\tinstallHelmRelease(name, &release)\n\t\t\twg.Done()\n\t\t}(name, release)\n\t}\n\n\tif previousConfig == nil {\n\t\twg.Wait()\n\t\treturn nil\n\t}\n\n\tfor name, release := range previousConfig.Releases {\n\t\twg.Add(1)\n\t\tgo func(name string, release cfg.Release) {\n\t\t\tif _, ok := config.Releases[name]; ok {\n\t\t\t\twg.Done()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tuninstallHelmRelease(name, &release)\n\t\t\twg.Done()\n\t\t}(name, release)\n\t}\n\n\twg.Wait()\n\n\treturn nil\n}\n\nfunc RunDown(config *cfg.Config) error {\n\tpreviousConfig, err := prov.Load(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif previousConfig != nil {\n\t\tconfig = previousConfig\n\t}\n\n\tvar wg sync.WaitGroup\n\n\tfor name, release := range config.Releases {\n\t\twg.Add(1)\n\t\tgo func(name string, release cfg.Release) {\n\t\t\tuninstallHelmRelease(name, &release)\n\t\t\twg.Done()\n\t\t}(name, release)\n\t}\n\n\twg.Wait()\n\n\treturn nil\n}\n\nfunc ListRevisions(config *cfg.Config) error {\n\trevisions, err := prov.List(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfmt.Printf(\"| Date             | Revision |\\n\")\n\tfmt.Printf(\"| ---------------- | -------- |\\n\")\n\tfor _, rev := range revisions {\n\t\tfmt.Printf(\"| %d-%02d-%02d %02d:%02d | %8d |\\n\",\n\t\t\trev.DateTime.Year(), rev.DateTime.Month(), rev.DateTime.Day(),\n\t\t\trev.DateTime.Hour(), rev.DateTime.Minute(), rev.Revision)\n\t}\n\n\treturn nil\n}\n\nfunc GetRevision(rev int, config *cfg.Config) error {\n\trevision, err := prov.Get(rev, config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfmt.Printf(\"%s\\n\", *revision)\n\n\treturn nil\n}\n\nfunc Template(config *cfg.Config, releases []string) error {\n\tutil.PrintColors = false\n\n\tfor name, url := range config.Repositories {\n\t\tif err := addHelmRepository(name, url); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tfor name, release := range config.Releases {\n\t\tif len(releases) == 0 {\n\t\t\ttemplateHelmRelease(name, &release)\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, rel := range releases {\n\t\t\tif rel == name {\n\t\t\t\ttemplateHelmRelease(name, &release)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/compose/helm.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage compose\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/Masterminds/semver\"\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/seacrew/helm-compose/internal/util\"\n)\n\nvar (\n\thelm       = os.Getenv(\"HELM_BIN\")\n\tversionRE  = regexp.MustCompile(`Version:\\s*\"([^\"]+)\"`)\n\tminVersion = semver.MustParse(\"v3.0.0\")\n)\n\ntype HelmCommand string\n\nconst (\n\tHELM_UPGRADE   HelmCommand = \"upgrade\"\n\tHELM_UNINSTALL HelmCommand = \"uninstall\"\n\tHELM_TEMPLATE  HelmCommand = \"template\"\n)\n\nfunc CompatibleHelmVersion() error {\n\tcmd := exec.Command(helm, \"version\")\n\tutil.DebugPrint(\"Executing %s\", strings.Join(cmd.Args, \" \"))\n\n\toutput, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to run `%s version`: %v\", os.Getenv(\"HELM_BIN\"), err)\n\t}\n\n\tversionOutput := string(output)\n\n\tmatches := versionRE.FindStringSubmatch(versionOutput)\n\tif matches == nil {\n\t\treturn fmt.Errorf(\"failed to find version in output %#v\", versionOutput)\n\t}\n\n\thelmVersion, err := semver.NewVersion(matches[1])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse version %#v: %v\", matches[1], err)\n\t}\n\n\tif minVersion.GreaterThan(helmVersion) {\n\t\treturn fmt.Errorf(\"helm compose requires at least helm version %s\", minVersion.String())\n\t}\n\treturn nil\n}\n\nfunc addHelmRepository(name string, url string) error {\n\toutput, err := util.Execute(helm, \"repo\", \"add\", \"--force-update\", name, url)\n\n\tif err != nil {\n\t\treturn errors.New(output)\n\t}\n\n\treturn nil\n}\n\nfunc installHelmRelease(name string, release *cfg.Release) {\n\targs, err := createHelmArguments(HELM_UPGRADE, name, release)\n\tif err != nil {\n\t\tcp := util.NewColorPrinter(name)\n\t\tcp.Printf(\"%s |\\t\\t%s\", name, err)\n\t}\n\n\thelmExec(name, args)\n}\n\nfunc templateHelmRelease(name string, release *cfg.Release) {\n\targs, err := createHelmArguments(HELM_TEMPLATE, name, release)\n\tif err != nil {\n\t\tcp := util.NewColorPrinter(name)\n\t\tcp.Printf(\"# %s |\\t\\t%s\", name, err)\n\t}\n\n\thelmExec(\"\", args)\n}\n\nfunc uninstallHelmRelease(name string, release *cfg.Release) {\n\tvar args []string\n\n\targs = append(args, \"uninstall\")\n\n\tif release.Namespace != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--namespace=%s\", release.Namespace))\n\t}\n\n\tif release.KubeConfig != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--kubeconfig=%s\", release.KubeConfig))\n\t}\n\n\tif release.KubeContext != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--kube-context=%s\", release.KubeContext))\n\t}\n\n\tif release.DeletionStrategy != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--cascade=%s\", release.DeletionStrategy))\n\t}\n\n\tif release.DeletionTimeout != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--timeout=%s\", release.DeletionTimeout))\n\t}\n\n\tif release.DeletionNoHooks {\n\t\targs = append(args, \"--no-hooks\")\n\t}\n\n\tif release.KeepHistory {\n\t\targs = append(args, \"--keep-history\")\n\t}\n\n\targs = append(args, name)\n\n\thelmExec(name, args)\n}\n\nfunc createHelmArguments(command HelmCommand, name string, release *cfg.Release) ([]string, error) {\n\tvar args []string\n\n\targs = append(args, string(command))\n\n\tif command == HELM_UPGRADE {\n\t\targs = append(args, \"--install\")\n\t}\n\n\tif release.ChartVersion != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--version=%s\", release.ChartVersion))\n\t}\n\n\tif release.Namespace != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--namespace=%s\", release.Namespace))\n\t}\n\n\tif release.ForceUpdate {\n\t\targs = append(args, \"--force\")\n\t}\n\n\tif release.HistoryMax < 0 {\n\t\targs = append(args, fmt.Sprintf(\"--history-max=%d\", 0))\n\t} else if release.HistoryMax > 0 {\n\t\targs = append(args, fmt.Sprintf(\"--history-max=%d\", release.HistoryMax))\n\t}\n\n\tif release.CreateNamespace {\n\t\targs = append(args, \"--create-namespace\")\n\t}\n\n\tif release.CleanUpOnFail {\n\t\targs = append(args, \"--cleanup-on-fail\")\n\t}\n\n\tif release.DependencyUpdate {\n\t\targs = append(args, \"--dependency-update\")\n\t}\n\n\tif release.SkipTLSVerify {\n\t\targs = append(args, \"--insecure-skip-tls-verify\")\n\t}\n\n\tif release.SkipCRDs {\n\t\targs = append(args, \"--skip-crds\")\n\t}\n\n\tif release.PostRenderer != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--post-renderer=%s\", release.PostRenderer))\n\t}\n\n\tif len(release.PostRendererArgs) > 0 {\n\t\targs = append(args, fmt.Sprintf(\"--post-renderer-args=[%s]\", strings.Join(release.PostRendererArgs, \",\")))\n\t}\n\n\tif release.CAFile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--ca-file=%s\", release.CAFile))\n\t}\n\n\tif release.CertFile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--cert-file=%s\", release.CertFile))\n\t}\n\n\tif release.KeyFile != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--key-file=%s\", release.KeyFile))\n\t}\n\n\tif release.Timeout != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--timeout=%s\", release.Timeout))\n\t}\n\n\tif release.Wait {\n\t\targs = append(args, \"--wait\")\n\t}\n\n\tif release.KubeConfig != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--kubeconfig=%s\", release.KubeConfig))\n\t}\n\n\tif release.KubeContext != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--kube-context=%s\", release.KubeContext))\n\t}\n\n\tfor _, file := range release.ValueFiles {\n\t\targs = append(args, fmt.Sprintf(\"--values=%s\", file))\n\t}\n\n\tvar jsonValues []string\n\tfor key := range release.Values {\n\t\tdata := util.ConvertJson(release.Values[key])\n\t\tvalues, err := json.Marshal(data)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tjsonValues = append(jsonValues, fmt.Sprintf(\"%s=%s\", key, values))\n\t}\n\n\tif len(jsonValues) > 0 {\n\t\targs = append(args, fmt.Sprintf(\"--set-json=%s\", strings.Join(jsonValues, \",\")))\n\t}\n\n\targs = append(args, name)\n\targs = append(args, release.Chart)\n\n\treturn args, nil\n}\n\nfunc helmExec(name string, args []string) {\n\tcp := util.NewColorPrinter(name)\n\toutput, _ := util.Execute(helm, args...)\n\n\tscanner := bufio.NewScanner(strings.NewReader(output))\n\tfor scanner.Scan() {\n\t\tif len(name) == 0 {\n\t\t\tfmt.Printf(\"%s\\n\", scanner.Text())\n\t\t} else {\n\t\t\tcp.Printf(\"%s |\\t\\t%s\", name, scanner.Text())\n\t\t}\n\t}\n\n\terr := scanner.Err()\n\n\tif err != nil {\n\t\tcp.Printf(err.Error())\n\t}\n}\n"
  },
  {
    "path": "internal/config/config.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage config\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/Masterminds/semver\"\n\t\"gopkg.in/yaml.v2\"\n)\n\nvar (\n\tV1_0 = semver.MustParse(\"1.0\")\n\tV1_1 = semver.MustParse(\"1.1\")\n)\n\nfunc findComposeConfig() []string {\n\tvar files []string\n\tfilenames := []string{\n\t\t\"helm-compose.yaml\",\n\t\t\"helm-compose.yml\",\n\t\t\"helmcompose.yaml\",\n\t\t\"helm-compose.yml\",\n\t\t\"helmcompose.yaml\",\n\t\t\"helmcompose.yml\",\n\t\t\"helmcompose\",\n\t\t\"compose.yaml\",\n\t\t\"compose.yml\",\n\t}\n\n\tfilepath.WalkDir(\".\", func(s string, d fs.DirEntry, e error) error {\n\t\tfile := filepath.Base(s)\n\n\t\tfor _, filename := range filenames {\n\t\t\tif file == filename {\n\t\t\t\tfiles = append(files, file)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\treturn files\n}\n\nfunc ParseComposeFile(filename string) (*Config, error) {\n\tvar files []string\n\tif filename == \"\" {\n\t\tfiles = findComposeConfig()\n\t} else if filename == \"-\" {\n\t\treader := bufio.NewReader(os.Stdin)\n\n\t\tdata := []byte{}\n\t\tfor {\n\t\t\tb, err := reader.ReadBytes('\\n')\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t} else if err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tdata = append(data, b...)\n\t\t}\n\n\t\treturn parseComposeData(data)\n\t} else if _, err := os.Stat(filename); err != nil {\n\t\treturn nil, fmt.Errorf(\"provided compose file not found\")\n\t} else {\n\t\tfiles = []string{filename}\n\t}\n\n\tif len(files) == 0 {\n\t\treturn nil, fmt.Errorf(\"no compose file found\")\n\t}\n\n\tif len(files) > 1 {\n\t\treturn nil, fmt.Errorf(\"expected only one compose file but found multiple: %v\", files)\n\t}\n\n\tfile, err := os.ReadFile(files[0])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn parseComposeData(file)\n}\n\nfunc parseComposeData(data []byte) (*Config, error) {\n\tconfig := Config{}\n\terr := yaml.Unmarshal(data, &config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := validateCompose(&config); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &config, nil\n}\n\nfunc validateCompose(config *Config) error {\n\tif config.Version == \"\" {\n\t\treturn fmt.Errorf(\"missing apiVersion in config\")\n\t}\n\n\tversion, err := semver.NewVersion(config.Version)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse apiVersion: %s\", config.Version)\n\t}\n\n\tif version.LessThan(V1_0) {\n\t\treturn fmt.Errorf(\"helm compose requires at least apiVersion 1.0 but got %s\", config.Version)\n\t}\n\n\tif err := validateComposeFeatures(version, config); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc validateComposeFeatures(version *semver.Version, config *Config) error {\n\tif err := validateCompose1_1(version, config); err != nil {\n\t\treturn fmt.Errorf(\"apiVersion 1.1+ necessary: %s\", err)\n\t}\n\n\treturn nil\n}\n\nfunc validateCompose1_1(version *semver.Version, config *Config) error {\n\tif version.GreaterThan(V1_0) {\n\t\treturn nil\n\t}\n\n\tfor name, release := range config.Releases {\n\t\tif release.Wait {\n\t\t\treturn fmt.Errorf(\"trying to use 'wait' in release '%s'\", name)\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/config/config_test.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage config\n\nimport (\n\t\"log\"\n\t\"testing\"\n)\n\nfunc TestParseSimpleConfig(t *testing.T) {\n\tconfig, err := ParseComposeFile(\"../../examples/simple-compose.yaml\")\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif config.Storage.Name != \"simple\" {\n\t\tlog.Fatalf(\"Was expecting revision name 'simple' but got '%s'\", config.Storage.Name)\n\t}\n\n\tif config.Storage.Type != Local {\n\t\tlog.Fatalf(\"Was expecting revision provider type '%s' but got '%s'\", Local, config.Storage.Type)\n\t}\n\n\tif len(config.Releases) != 2 {\n\t\tlog.Fatalf(\"Was expecting 2 release but got %d\", len(config.Releases))\n\t}\n}\n"
  },
  {
    "path": "internal/config/types.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage config\n\nimport \"reflect\"\n\ntype ProviderType string\n\nconst (\n\tLocal      ProviderType = \"local\"\n\tKubernetes ProviderType = \"kubernetes\"\n\tS3         ProviderType = \"s3\"\n)\n\ntype Config struct {\n\tVersion      string             `yaml:\"apiVersion,omitempty\"`\n\tStorage      Storage            `yaml:\"storage,omitempty\"`\n\tReleases     map[string]Release `yaml:\"releases,omitempty\"`\n\tRepositories map[string]string  `yaml:\"repositories,omitempty\"`\n}\n\ntype Release struct {\n\tName             string                 `yaml:\"name,omitempty\"`\n\tChart            string                 `yaml:\"chart,omitempty\"`\n\tChartVersion     string                 `yaml:\"chartVersion,omitempty\"`\n\tNamespace        string                 `yaml:\"namespace,omitempty\"`\n\tForceUpdate      bool                   `yaml:\"forceUpdate,omitempty\"`\n\tHistoryMax       int                    `yaml:\"historyMax,omitempty\"`\n\tCreateNamespace  bool                   `yaml:\"createNamespace,omitempty\"`\n\tCleanUpOnFail    bool                   `yaml:\"cleanupOnFail,omitempty\"`\n\tDependencyUpdate bool                   `yaml:\"dependencyUpdate,omitempty\"`\n\tSkipTLSVerify    bool                   `yaml:\"skipTlsVerify,omitempty\"`\n\tSkipCRDs         bool                   `yaml:\"skipCrds,omitempty\"`\n\tPostRenderer     string                 `yaml:\"postRenderer,omitempty\"`\n\tPostRendererArgs []string               `yaml:\"postRendererArgs,omitempty\"`\n\tKubeConfig       string                 `yaml:\"kubeconfig,omitempty\"`\n\tKubeContext      string                 `yaml:\"kubecontext,omitempty\"`\n\tCAFile           string                 `yaml:\"caFile,omitempty\"`\n\tCertFile         string                 `yaml:\"certFile,omitempty\"`\n\tKeyFile          string                 `yaml:\"keyFile,omitempty\"`\n\tTimeout          string                 `yaml:\"timeout,omitempty\"`\n\tWait             bool                   `yaml:\"wait,omitempty\"`\n\tValues           map[string]interface{} `yaml:\"values,omitempty\"`\n\tValueFiles       []string               `yaml:\"valueFiles,omitempty\"`\n\n\t// Uninstall flags\n\tDeletionStrategy string `yaml:\"deletionStrategy,omitempty\"`\n\tDeletionTimeout  string `yaml:\"deletionTimeout,omitempty\"`\n\tDeletionNoHooks  bool   `yaml:\"deletionNoHooks,omitempty\"`\n\tKeepHistory      bool   `yaml:\"keepHistory,omitempty\"`\n}\n\ntype Storage struct {\n\tType              ProviderType `yaml:\"type,omitempty\"`\n\tName              string       `yaml:\"name,omitempty\"`\n\tNumberOfRevisions int          `yaml:\"numberOfRevisions,omitempty\"`\n\t// Local storage fields\n\tPath string `yaml:\"path,omitempty\"`\n\t// K8s storage fields\n\tNamespace   string `yaml:\"namespace,omitempty\"`\n\tKubeConfig  string `yaml:\"kubeconfig,omitempty\"`\n\tKubeContext string `yaml:\"kubecontext,omitempty\"`\n\t// S3 storage fields\n\tS3Bucket         string `yaml:\"s3bucket,omitempty\"`\n\tS3Prefix         string `yaml:\"s3prefix,omitempty\"`\n\tS3Region         string `yaml:\"s3region,omitempty\"`\n\tS3Endpoint       string `yaml:\"s3endpoint,omitempty\"`\n\tS3Insecure       bool   `yaml:\"s3insecure,omitempty\"`\n\tS3DisableSSL     bool   `yaml:\"s3disableSSL,omitempty\"`\n\tS3ForcePathStyle bool   `yaml:\"s3forcePathStyle,omitempty\"`\n}\n\nfunc (c *Config) Equal(o *Config) bool {\n\tif o == nil {\n\t\treturn false\n\t}\n\n\tif c.Version != o.Version {\n\t\treturn false\n\t}\n\n\tif c.Storage != o.Storage {\n\t\treturn false\n\t}\n\n\tif len(c.Releases) != len(o.Releases) {\n\t\treturn false\n\t}\n\n\tif !reflect.DeepEqual(c.Releases, o.Releases) {\n\t\treturn false\n\t}\n\n\tif len(c.Repositories) != len(o.Repositories) {\n\t\treturn false\n\t}\n\n\tfor key, value := range c.Repositories {\n\t\tif val, ok := o.Repositories[key]; !ok || val != value {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "internal/config/types_test.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage config\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestConfigEqualVersion(t *testing.T) {\n\tcfg := Config{Version: \"v1.0\"}\n\totherCfg := Config{Version: \"v1.0\"}\n\tassert.True(t, cfg.Equal(&otherCfg))\n\n\tcfg = Config{Version: \"v1.0\"}\n\totherCfg = Config{Version: \"v1.1\"}\n\tassert.False(t, cfg.Equal(&otherCfg))\n\n}\n\nfunc TestConfigEqualStorage(t *testing.T) {\n\tcfg := Config{\n\t\tStorage: Storage{\n\t\t\tType: Local,\n\t\t\tName: \"mycompose\",\n\t\t\tPath: \".state\",\n\t\t},\n\t}\n\tassert.True(t, cfg.Equal(&cfg))\n\n\totherCfg := Config{\n\t\tStorage: Storage{\n\t\t\tType: Local,\n\t\t\tName: \"mycompose\",\n\t\t},\n\t}\n\tassert.False(t, cfg.Equal(&otherCfg))\n}\n\nfunc TestConfigEqualRepositories(t *testing.T) {\n\tcfg := Config{\n\t\tRepositories: map[string]string{},\n\t}\n\n\totherCfg := Config{\n\t\tRepositories: map[string]string{\n\t\t\t\"bitnami\": \"https://charts.bitnami.com/bitnami\",\n\t\t},\n\t}\n\tassert.False(t, cfg.Equal(&otherCfg))\n\n\tcfg = Config{\n\t\tRepositories: map[string]string{\n\t\t\t\"bitnami\": \"https://charts.bitnami.com/bitnami\",\n\t\t},\n\t}\n\n\totherCfg = Config{\n\t\tRepositories: map[string]string{\n\t\t\t\"bitnami\": \"https://charts.bitnami.com/bitnami\",\n\t\t},\n\t}\n\tassert.True(t, cfg.Equal(&otherCfg))\n\n\tcfg = Config{\n\t\tRepositories: map[string]string{\n\t\t\t\"bitnami\": \"https://charts.bitnami.com/bitnami\",\n\t\t},\n\t}\n\n\totherCfg = Config{\n\t\tRepositories: map[string]string{\n\t\t\t\"bitnami\": \"https://charts.bitnami.net/bitnami\",\n\t\t},\n\t}\n\tassert.False(t, cfg.Equal(&otherCfg))\n}\n\nfunc TestConfigEqualReleases(t *testing.T) {\n\tcfg := Config{\n\t\tReleases: map[string]Release{},\n\t}\n\n\totherCfg := Config{\n\t\tReleases: map[string]Release{\n\t\t\t\"wordpress\": {\n\t\t\t\tChart:        \"bitnami/wordpress\",\n\t\t\t\tChartVersion: \"14.2.1\",\n\t\t\t},\n\t\t},\n\t}\n\tassert.False(t, cfg.Equal(&otherCfg))\n\n\tcfg = Config{\n\t\tReleases: map[string]Release{\n\t\t\t\"wordpress\": {\n\t\t\t\tChart:        \"bitnami/wordpress\",\n\t\t\t\tChartVersion: \"14.2.1\",\n\t\t\t\tValues: map[string]interface{}{\n\t\t\t\t\t\"wordpressBlogName\": \"my-site\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\totherCfg = Config{\n\t\tReleases: map[string]Release{\n\t\t\t\"wordpress\": {\n\t\t\t\tChart:        \"bitnami/wordpress\",\n\t\t\t\tChartVersion: \"14.2.1\",\n\t\t\t\tValues: map[string]interface{}{\n\t\t\t\t\t\"wordpressBlogName\": \"my-site\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tassert.True(t, cfg.Equal(&otherCfg))\n\n\tcfg = Config{\n\t\tReleases: map[string]Release{\n\t\t\t\"wordpress\": {\n\t\t\t\tChart:        \"bitnami/wordpress\",\n\t\t\t\tChartVersion: \"14.2.1\",\n\t\t\t\tValues: map[string]interface{}{\n\t\t\t\t\t\"wordpressBlogName\": \"my-site\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\totherCfg = Config{\n\t\tReleases: map[string]Release{\n\t\t\t\"wordpress\": {\n\t\t\t\tChart:        \"bitnami/wordpress\",\n\t\t\t\tChartVersion: \"14.2.1\",\n\t\t\t\tValues: map[string]interface{}{\n\t\t\t\t\t\"wordpressBlogName\": \"my-new-site\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tassert.False(t, cfg.Equal(&otherCfg))\n}\n"
  },
  {
    "path": "internal/provider/kubernetes.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage provider\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\n\tb64 \"encoding/base64\"\n\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/seacrew/helm-compose/internal/util\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n)\n\nconst (\n\tk8sSecretNameFormat  = \"helm.compose.%s.v%d\"\n\tk8sSecretNamePattern = \"^helm.compose.%s.v(\\\\d+)$\"\n)\n\ntype KubernetesProvider struct {\n\tname              string\n\tnumberOfRevisions int\n\tnamespace         string\n\tclient            *kubernetes.Clientset\n\tlistOptions       *metav1.ListOptions\n}\n\nfunc newKubernetesProvider(providerConfig *cfg.Storage) (*KubernetesProvider, error) {\n\tnamespace := providerConfig.Namespace\n\tif len(namespace) == 0 {\n\t\tnamespace = \"default\"\n\t}\n\n\tkubeconfig := providerConfig.KubeConfig\n\tif len(kubeconfig) == 0 {\n\t\thomedir, err := os.UserHomeDir()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tkubeconfig = filepath.Join(\n\t\t\thomedir, \".kube\", \"config\",\n\t\t)\n\t}\n\n\tvar err error\n\tvar config *rest.Config\n\n\tif len(providerConfig.KubeContext) == 0 {\n\t\tconfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}, &clientcmd.ConfigOverrides{CurrentContext: providerConfig.KubeContext}).ClientConfig()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\tconfig, err = clientcmd.BuildConfigFromFlags(\"\", kubeconfig)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t}\n\n\tclientset, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlabelSelector := metav1.LabelSelector{MatchLabels: map[string]string{\"app.kubernetes.io/managed-by\": \"Helm-Compose\", \"helm-compose/name\": providerConfig.Name}}\n\tlistOptions := metav1.ListOptions{\n\t\tLabelSelector: labels.Set(labelSelector.MatchLabels).String(),\n\t}\n\n\tprovider := &KubernetesProvider{\n\t\tname:              providerConfig.Name,\n\t\tnumberOfRevisions: providerConfig.NumberOfRevisions,\n\t\tnamespace:         namespace,\n\t\tclient:            clientset,\n\t\tlistOptions:       &listOptions,\n\t}\n\n\treturn provider, nil\n}\n\nfunc (p KubernetesProvider) load() (*[]byte, error) {\n\tsecrets, err := p.client.CoreV1().Secrets(p.namespace).List(context.Background(), *p.listOptions)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(secrets.Items) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t_, _, latest, err := p.minMax(secrets.Items)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif latest == nil {\n\t\treturn nil, nil\n\t}\n\n\tdata, err := b64.StdEncoding.DecodeString(string(latest.Data[\"compose\"]))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &data, nil\n}\n\nfunc (p KubernetesProvider) store(encodedConfig *string) error {\n\tsecrets, err := p.client.CoreV1().Secrets(p.namespace).List(context.Background(), *p.listOptions)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tminimum, maximum, _, err := p.minMax(secrets.Items)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\trevision := maximum + 1\n\n\tdata := b64.StdEncoding.EncodeToString([]byte(*encodedConfig))\n\n\tsecret := &corev1.Secret{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      fmt.Sprintf(k8sSecretNameFormat, p.name, revision),\n\t\t\tNamespace: p.namespace,\n\t\t\tLabels: map[string]string{\n\t\t\t\t\"app.kubernetes.io/managed-by\": \"Helm-Compose\",\n\t\t\t\t\"helm-compose/name\":            p.name,\n\t\t\t},\n\t\t},\n\t\tImmutable: util.NewBool(true),\n\t\tData: map[string][]byte{\n\t\t\t\"compose\": []byte(data),\n\t\t},\n\t\tType: \"helm-compose/revision.v1\",\n\t}\n\n\t_, err = p.client.CoreV1().Secrets(p.namespace).Create(context.Background(), secret, metav1.CreateOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif minimum > revision-p.numberOfRevisions {\n\t\treturn nil\n\t}\n\n\tfor i := minimum; i <= revision-p.numberOfRevisions; i++ {\n\t\tif err = p.client.CoreV1().Secrets(p.namespace).Delete(context.Background(), fmt.Sprintf(k8sSecretNameFormat, p.name, i), metav1.DeleteOptions{}); err != nil {\n\t\t\tfmt.Println(err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (p KubernetesProvider) list() ([]ComposeRevision, error) {\n\tsecrets, err := p.client.CoreV1().Secrets(p.namespace).List(context.Background(), metav1.ListOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(secrets.Items) == 0 {\n\t\treturn nil, nil\n\t}\n\n\trevisions := []ComposeRevision{}\n\n\tr, err := regexp.Compile(fmt.Sprintf(k8sSecretNamePattern, p.name))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, item := range secrets.Items {\n\t\tmatches := r.FindStringSubmatch(item.Name)\n\t\tif len(matches) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\trevision, err := strconv.Atoi(matches[1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\trevisions = append(revisions, ComposeRevision{revision, item.CreationTimestamp.Time})\n\t}\n\n\treturn revisions, nil\n}\n\nfunc (p KubernetesProvider) get(revision int) (*[]byte, error) {\n\tsecret, err := p.client.CoreV1().Secrets(p.namespace).Get(context.Background(), fmt.Sprintf(k8sSecretNameFormat, p.name, revision), metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdata, err := b64.StdEncoding.DecodeString(string(secret.Data[\"compose\"]))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &data, nil\n}\n\nfunc (p KubernetesProvider) minMax(secrets []corev1.Secret) (int, int, *corev1.Secret, error) {\n\tif len(secrets) == 0 {\n\t\treturn 0, 0, nil, nil\n\t}\n\n\tminimum, maximum := math.MaxInt, 0\n\n\tr, err := regexp.Compile(fmt.Sprintf(k8sSecretNamePattern, p.name))\n\tif err != nil {\n\t\treturn -1, -1, nil, err\n\t}\n\n\tvar latest corev1.Secret\n\n\tfor _, secret := range secrets {\n\t\tmatches := r.FindStringSubmatch(secret.Name)\n\t\tif len(matches) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\trevision, err := strconv.Atoi(matches[1])\n\t\tif err != nil {\n\t\t\treturn -1, -1, nil, err\n\t\t}\n\n\t\tif revision > maximum {\n\t\t\tmaximum = revision\n\t\t\tlatest = secret\n\t\t}\n\n\t\tif revision < minimum {\n\t\t\tminimum = revision\n\t\t}\n\t}\n\n\treturn minimum, maximum, &latest, nil\n}\n"
  },
  {
    "path": "internal/provider/kubernetes_test.go",
    "content": "package provider\n\nimport (\n\t\"testing\"\n)\n\nfunc TestStoreAndLoad(t *testing.T) {\n\t//k8s, err := newKubernetes(&config.Storage{\n\t//\tName: \"hello-world\",\n\t//})\n\n\t//if err != nil {\n\t//\tlog.Fatal(err)\n\t//}\n\n\t//_, err = k8s.load()\n\t//if err != nil {\n\t//\tlog.Fatal(err)\n\t//}\n}\n"
  },
  {
    "path": "internal/provider/local.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage provider\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/seacrew/helm-compose/internal/util\"\n)\n\nconst (\n\tpathFormat = \"%s/%s-%d\"\n)\n\ntype LocalProvider struct {\n\tname              string\n\tpath              string\n\tnumberOfRevisions int\n}\n\nfunc newLocalProvider(providerConfig *cfg.Storage) *LocalProvider {\n\tprovider := LocalProvider{\n\t\tname:              providerConfig.Name,\n\t\tpath:              providerConfig.Path,\n\t\tnumberOfRevisions: providerConfig.NumberOfRevisions,\n\t}\n\n\tif len(provider.path) == 0 {\n\t\tprovider.path = \".hcstate\"\n\t}\n\n\treturn &provider\n}\n\nfunc (p LocalProvider) load() (*[]byte, error) {\n\tif _, err := os.Stat(p.path); os.IsNotExist(err) {\n\t\tif err := os.Mkdir(p.path, os.ModePerm); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t_, maximum, err := p.minMax(p.name, p.path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif maximum == 0 {\n\t\treturn nil, nil\n\t}\n\n\tfile, err := os.ReadFile(fmt.Sprintf(pathFormat, p.path, p.name, maximum))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &file, nil\n}\n\nfunc (p LocalProvider) store(encodedConfig *string) error {\n\tminimum, maximum, err := p.minMax(p.name, p.path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmaximum = maximum + 1\n\n\tif err := os.WriteFile(fmt.Sprintf(pathFormat, p.path, p.name, maximum), []byte(*encodedConfig), 0644); err != nil {\n\t\treturn err\n\t}\n\n\tif minimum > maximum-p.numberOfRevisions {\n\t\treturn nil\n\t}\n\n\tfor i := minimum; i <= maximum-p.numberOfRevisions; i++ {\n\t\tif err := os.Remove(fmt.Sprintf(pathFormat, p.path, p.name, i)); err != nil {\n\t\t\tfmt.Println(err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (p LocalProvider) list() ([]ComposeRevision, error) {\n\tfiles, err := os.ReadDir(p.path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tr, _ := regexp.Compile(fmt.Sprintf(\"^%s-(\\\\d+)$\", p.name))\n\n\trevisions := []ComposeRevision{}\n\tfor _, file := range files {\n\t\tif file.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tmatches := r.FindStringSubmatch(file.Name())\n\t\tif len(matches) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\trevision, err := strconv.Atoi(matches[1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tinfo, err := file.Info()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\trevisions = append(revisions, ComposeRevision{revision, info.ModTime()})\n\t}\n\n\treturn revisions, nil\n}\n\nfunc (p LocalProvider) get(revision int) (*[]byte, error) {\n\tfile, err := os.ReadFile(fmt.Sprintf(pathFormat, p.path, p.name, revision))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &file, nil\n}\n\nfunc (p LocalProvider) minMax(name string, path string) (int, int, error) {\n\tfiles, err := os.ReadDir(path)\n\tif err != nil {\n\t\treturn -1, -1, err\n\t}\n\n\tr, _ := regexp.Compile(fmt.Sprintf(\"^%s-(\\\\d+)$\", name))\n\n\trevisions := []int{}\n\tfor _, file := range files {\n\t\tif file.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tmatches := r.FindStringSubmatch(file.Name())\n\t\tif len(matches) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\trevision, err := strconv.Atoi(matches[1])\n\t\tif err != nil {\n\t\t\treturn -1, -1, nil\n\t\t}\n\n\t\trevisions = append(revisions, revision)\n\t}\n\n\tminimum, maximum := util.MinMax(revisions)\n\treturn minimum, maximum, nil\n}\n"
  },
  {
    "path": "internal/provider/providers.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage provider\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"time\"\n\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/seacrew/helm-compose/internal/util\"\n\t\"gopkg.in/yaml.v2\"\n)\n\ntype ComposeRevision struct {\n\tRevision int\n\tDateTime time.Time\n}\n\ntype Provider interface {\n\tload() (*[]byte, error)\n\tstore(encodedConfig *string) error\n\tlist() ([]ComposeRevision, error)\n\tget(revision int) (*[]byte, error)\n}\n\nvar provider Provider\n\nfunc getProvider(providerConfig *cfg.Storage) (Provider, error) {\n\tif provider != nil {\n\t\treturn provider, nil\n\t}\n\n\tif providerConfig.NumberOfRevisions <= 0 {\n\t\tproviderConfig.NumberOfRevisions = 10\n\t}\n\n\tvar err error\n\n\tswitch providerConfig.Type {\n\tcase cfg.Local:\n\t\tprovider = newLocalProvider(providerConfig)\n\t\treturn provider, nil\n\tcase cfg.Kubernetes:\n\t\tprovider, err = newKubernetesProvider(providerConfig)\n\t\treturn provider, err\n\tcase cfg.S3:\n\t\tprovider, err = newS3Provider(providerConfig)\n\t\treturn provider, err\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown provider type %q\", providerConfig.Type)\n\t}\n}\n\nfunc Load(config *cfg.Config) (*cfg.Config, error) {\n\tprovider, err := getProvider(&config.Storage)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdata, err := provider.load()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif data == nil {\n\t\treturn nil, nil\n\t}\n\n\tprevConfig, err := util.DecodeComposeConfig(string(*data))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn prevConfig, nil\n}\n\nfunc Store(config *cfg.Config) error {\n\tprovider, err := getProvider(&config.Storage)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tencodedConfig, err := util.EncodeComposeConfig(config)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := provider.store(&encodedConfig); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc List(config *cfg.Config) ([]ComposeRevision, error) {\n\tprovider, err := getProvider(&config.Storage)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trevisions, err := provider.list()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsort.Slice(revisions, func(i, j int) bool {\n\t\treturn revisions[i].Revision < revisions[j].Revision\n\t})\n\n\treturn revisions, nil\n}\n\nfunc Get(revision int, config *cfg.Config) (*string, error) {\n\tprovider, err := getProvider(&config.Storage)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdata, err := provider.get(revision)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trevConfig, err := util.DecodeComposeConfig(string(*data))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tb, err := yaml.Marshal(revConfig)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trevYaml := string(b)\n\treturn &revYaml, nil\n}\n"
  },
  {
    "path": "internal/provider/s3.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage provider\n\nimport (\n\t\"bytes\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"math\"\n\t\"net/http\"\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\n\t\"github.com/aws/aws-sdk-go/aws\"\n\t\"github.com/aws/aws-sdk-go/aws/session\"\n\t\"github.com/aws/aws-sdk-go/service/s3\"\n\t\"github.com/aws/aws-sdk-go/service/s3/s3manager\"\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n\t\"github.com/seacrew/helm-compose/internal/util\"\n)\n\nconst (\n\ts3ObjectNameFormat  = \"%s.v%d.hcstate\"\n\ts3ObjectNamePattern = \"%s.v(\\\\d+).hcstate$\"\n)\n\ntype S3Provider struct {\n\tname              string\n\tnumberOfRevisions int\n\tbucket            *string\n\tprefix            *string\n\tlister            *s3.S3\n\tuploader          *s3manager.Uploader\n\tdownloader        *s3manager.Downloader\n}\n\nfunc newS3Provider(providerConfig *cfg.Storage) (*S3Provider, error) {\n\tconfig := &aws.Config{}\n\n\tif len(providerConfig.S3Region) > 0 {\n\t\tconfig.Region = &providerConfig.S3Region\n\t} else if os.Getenv(\"AWS_REGION\") != \"\" {\n\t\tconfig.Region = aws.String(os.Getenv(\"AWS_REGION\"))\n\t} else {\n\t\treturn nil, fmt.Errorf(\"AWS region not specified\")\n\t}\n\n\tif len(providerConfig.S3Endpoint) > 0 {\n\t\tconfig.Endpoint = &providerConfig.S3Endpoint\n\t}\n\n\tif providerConfig.S3DisableSSL {\n\t\tconfig.DisableSSL = util.NewBool(true)\n\t}\n\n\tif providerConfig.S3Insecure {\n\t\ttr := &http.Transport{\n\t\t\tTLSClientConfig: &tls.Config{InsecureSkipVerify: true},\n\t\t}\n\t\tconfig.HTTPClient = &http.Client{Transport: tr}\n\t}\n\n\tif providerConfig.S3ForcePathStyle {\n\t\tconfig.S3ForcePathStyle = util.NewBool(true)\n\t}\n\n\tsess, err := session.NewSession(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tprovider := &S3Provider{\n\t\tname:              providerConfig.Name,\n\t\tnumberOfRevisions: providerConfig.NumberOfRevisions,\n\t\tbucket:            &providerConfig.S3Bucket,\n\t\tprefix:            &providerConfig.S3Prefix,\n\t\tlister:            s3.New(sess),\n\t\tuploader:          s3manager.NewUploader(sess),\n\t\tdownloader:        s3manager.NewDownloader(sess),\n\t}\n\n\treturn provider, nil\n}\n\nfunc (p S3Provider) load() (*[]byte, error) {\n\tresp, err := p.lister.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: p.bucket, Prefix: p.prefix})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(resp.Contents) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t_, _, latest, err := p.minMax(resp.Contents)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif latest == nil {\n\t\treturn nil, nil\n\t}\n\n\tbuff := &aws.WriteAtBuffer{}\n\tif _, err := p.downloader.Download(buff, &s3.GetObjectInput{Bucket: p.bucket, Key: latest.Key}); err != nil {\n\t\treturn nil, err\n\t}\n\n\tcontent := buff.Bytes()\n\treturn &content, nil\n}\n\nfunc (p S3Provider) store(encodedConfig *string) error {\n\tresp, err := p.lister.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: p.bucket, Prefix: p.prefix})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tminimum, maximum, _, err := p.minMax(resp.Contents)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\trevision := maximum + 1\n\n\tkey := fmt.Sprintf(s3ObjectNameFormat, p.name, revision)\n\tif len(*p.prefix) > 0 {\n\t\tkey = fmt.Sprintf(\"%s/%s\", *p.prefix, key)\n\t}\n\n\treader := bytes.NewReader([]byte(*encodedConfig))\n\n\t_, err = p.uploader.Upload(\n\t\t&s3manager.UploadInput{\n\t\t\tBucket: p.bucket,\n\t\t\tKey:    &key,\n\t\t\tBody:   reader,\n\t\t})\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif minimum > revision-p.numberOfRevisions {\n\t\treturn nil\n\t}\n\n\tfor i := minimum; i < revision-p.numberOfRevisions; i++ {\n\t\tkey := fmt.Sprintf(s3ObjectNameFormat, p.name, i)\n\t\tif len(*p.prefix) > 0 {\n\t\t\tkey = fmt.Sprintf(\"%s/%s\", *p.prefix, key)\n\t\t}\n\n\t\t_, err := p.lister.DeleteObject(&s3.DeleteObjectInput{Bucket: p.bucket, Key: &key})\n\t\tif err != nil {\n\t\t\tfmt.Println(err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (p S3Provider) list() ([]ComposeRevision, error) {\n\tresp, err := p.lister.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: p.bucket, Prefix: p.prefix})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar revisions []ComposeRevision\n\n\tr, err := regexp.Compile(fmt.Sprintf(s3ObjectNamePattern, p.name))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, item := range resp.Contents {\n\t\tmatches := r.FindStringSubmatch(*item.Key)\n\t\tif len(matches) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\trevision, err := strconv.Atoi(matches[1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\trevisions = append(revisions, ComposeRevision{revision, *item.LastModified})\n\t}\n\n\treturn revisions, nil\n}\n\nfunc (p S3Provider) get(revision int) (*[]byte, error) {\n\tkey := fmt.Sprintf(s3ObjectNameFormat, p.name, revision)\n\tif len(*p.prefix) > 0 {\n\t\tkey = fmt.Sprintf(\"%s/%s\", *p.prefix, key)\n\t}\n\n\tbuff := &aws.WriteAtBuffer{}\n\t_, err := p.downloader.Download(buff,\n\t\t&s3.GetObjectInput{\n\t\t\tBucket: p.bucket,\n\t\t\tKey:    &key,\n\t\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcontent := buff.Bytes()\n\treturn &content, nil\n}\n\nfunc (p S3Provider) minMax(objects []*s3.Object) (int, int, *s3.Object, error) {\n\tif len(objects) == 0 {\n\t\treturn 0, 0, nil, nil\n\t}\n\n\tminimum, maximum := math.MaxInt, 0\n\tvar latest *s3.Object\n\n\tr, err := regexp.Compile(fmt.Sprintf(s3ObjectNamePattern, p.name))\n\tif err != nil {\n\t\treturn -1, -1, nil, err\n\t}\n\n\tfor _, item := range objects {\n\t\tmatches := r.FindStringSubmatch(*item.Key)\n\n\t\tif len(matches) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\trevision, err := strconv.Atoi(matches[1])\n\t\tif err != nil {\n\t\t\treturn -1, -1, nil, err\n\t\t}\n\n\t\tif revision < minimum {\n\t\t\tminimum = revision\n\t\t}\n\n\t\tif revision > maximum {\n\t\t\tmaximum = revision\n\t\t\tlatest = item\n\t\t}\n\t}\n\n\treturn minimum, maximum, latest, nil\n}\n"
  },
  {
    "path": "internal/provider/s3_test.go",
    "content": "package provider\n\nimport (\n\t\"log\"\n\t\"testing\"\n\n\tcfg \"github.com/seacrew/helm-compose/internal/config\"\n)\n\nfunc TestS3List(t *testing.T) {\n\tconfig := &cfg.Storage{\n\t\tName:              \"test\",\n\t\tNumberOfRevisions: 5,\n\t\tS3Bucket:          \"helm-compose\",\n\t\tS3Prefix:          \"test\",\n\t\tS3Region:          \"eu-central-1\",\n\t}\n\n\tprovider, err := newS3Provider(config)\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\trevisions, err := provider.list()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tlog.Fatal(revisions)\n}\n"
  },
  {
    "path": "internal/util/colors.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage util\n\nimport (\n\t\"fmt\"\n\t\"hash/fnv\"\n\t\"strconv\"\n\n\t\"github.com/jwalton/go-supportscolor\"\n)\n\ntype ColorPrinter struct {\n\tcolorFunc func(...interface{}) string\n}\n\nvar PrintColors = true\n\nfunc NewColorPrinter(s string) *ColorPrinter {\n\tc := hashColor(s)\n\treturn &ColorPrinter{\n\t\tcolorFunc: c,\n\t}\n}\n\nfunc (c ColorPrinter) Printf(format string, a ...any) {\n\tif PrintColors {\n\t\tfmt.Printf(c.colorFunc(format)+\"\\n\", a...)\n\t\treturn\n\t}\n\n\tfmt.Printf(format+\"\\n\", a...)\n}\n\nvar colorFuncs [](func(...interface{}) string) = [](func(...interface{}) string){\n\tcolor(\"%s\"), // fallback\n\tcolor(\"\\033[1;32m%s\\033[0m\"),\n\tcolor(\"\\033[1;33m%s\\033[0m\"),\n\tcolor(\"\\033[1;34m%s\\033[0m\"),\n\tcolor(\"\\033[1;35m%s\\033[0m\"),\n\tcolor(\"\\033[1;36m%s\\033[0m\"),\n\tcolor(\"\\033[1;90m%s\\033[0m\"),\n\tcolor(\"\\033[1;92m%s\\033[0m\"),\n\tcolor(\"\\033[1;93m%s\\033[0m\"),\n\tcolor(\"\\033[1;94m%s\\033[0m\"),\n\tcolor(\"\\033[1;95m%s\\033[0m\"),\n\tcolor(\"\\033[1;96m%s\\033[0m\"),\n}\n\nfunc color(colorString string) func(...interface{}) string {\n\tsprint := func(args ...interface{}) string {\n\t\treturn fmt.Sprintf(colorString,\n\t\t\tfmt.Sprint(args...))\n\t}\n\treturn sprint\n}\n\nfunc hashColor(s string) func(...interface{}) string {\n\tif !supportscolor.Stdout().SupportsColor {\n\t\treturn colorFuncs[0]\n\t}\n\n\th := fnv.New32a()\n\th.Write([]byte(s))\n\n\thash := fmt.Sprint(h.Sum32())\n\tfor {\n\t\tsubtotal := 0\n\t\tfor _, r := range hash {\n\t\t\tvalue, _ := strconv.Atoi(string(r))\n\t\t\tsubtotal += value\n\t\t}\n\n\t\tif subtotal < len(colorFuncs) {\n\t\t\treturn colorFuncs[subtotal]\n\t\t}\n\n\t\thash = fmt.Sprint(subtotal)\n\t}\n}\n"
  },
  {
    "path": "internal/util/encoding.go",
    "content": "/*\nCopyright 2016 The Kubernetes Authors All Rights Reserved\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage util\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"encoding/base64\"\n\t\"io/ioutil\"\n\n\tc \"github.com/seacrew/helm-compose/internal/config\"\n\t\"gopkg.in/yaml.v2\"\n)\n\nvar b64 = base64.StdEncoding\n\nvar magicGzip = []byte{0x1f, 0x8b, 0x08}\n\n// encodeComposeConfig encodes the config file returning a base64 encoded\n// gzipped string representation, or error.\nfunc EncodeComposeConfig(config *c.Config) (string, error) {\n\tb, err := yaml.Marshal(config)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tvar buf bytes.Buffer\n\tw, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif _, err = w.Write(b); err != nil {\n\t\treturn \"\", err\n\t}\n\tw.Close()\n\n\treturn b64.EncodeToString(buf.Bytes()), nil\n}\n\n// decodeComposeConfig decodes the bytes of data into a compose\n// config. Data must contain a base64 encoded gzipped string of a\n// valid release, otherwise an error is returned.\nfunc DecodeComposeConfig(data string) (*c.Config, error) {\n\t// base64 decode string\n\tb, err := b64.DecodeString(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tr, err := gzip.NewReader(bytes.NewReader(b))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer r.Close()\n\tb2, err := ioutil.ReadAll(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tb = b2\n\n\tvar config c.Config\n\t// unmarshal release object bytes\n\tif err := yaml.Unmarshal(b, &config); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &config, nil\n}\n"
  },
  {
    "path": "internal/util/util.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage util\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strings\"\n)\n\nvar (\n\tre = regexp.MustCompile(`\\$\\{(.*?)\\}`)\n)\n\nfunc IsDebug() bool {\n\treturn os.Getenv(\"HELM_DEBUG\") == \"true\"\n}\n\nfunc DebugPrint(format string, a ...interface{}) {\n\tif IsDebug() {\n\t\tfmt.Printf(format+\"\\n\", a...)\n\t}\n}\n\nfunc Execute(command string, args ...string) (string, error) {\n\tcmd := exec.Command(command, args...)\n\toutput, err := cmd.CombinedOutput()\n\n\tif output == nil {\n\t\treturn \"\", err\n\t}\n\n\ttext := string(output)\n\n\tif len(text) > 5 && text[:6] == \"Error:\" {\n\t\ttext = strings.TrimSpace(text[6:])\n\t}\n\n\treturn text, err\n}\n\nfunc ConvertJson(obj interface{}) interface{} {\n\tswitch c := obj.(type) {\n\tcase map[interface{}]interface{}:\n\t\tm := map[string]interface{}{}\n\t\tfor k, v := range c {\n\t\t\tm[k.(string)] = ConvertJson(v)\n\t\t}\n\t\treturn m\n\tcase []interface{}:\n\t\tfor k, v := range c {\n\t\t\tc[k] = ConvertJson(v)\n\t\t}\n\tcase string:\n\t\tstr := obj.(string)\n\t\tmatches := re.FindStringSubmatch(str)\n\t\tfor _, match := range matches {\n\t\t\tstr = strings.Replace(str, \"${\"+match+\"}\", os.Getenv(match), 1)\n\t\t}\n\n\t\treturn str\n\t}\n\treturn obj\n}\n\nfunc MinMax(ints []int) (int, int) {\n\tif len(ints) == 0 {\n\t\treturn 0, 0\n\t}\n\n\tminimum, maximum := math.MaxInt, 0\n\n\tfor _, i := range ints {\n\t\tif i > maximum {\n\t\t\tmaximum = i\n\t\t}\n\n\t\tif i < minimum {\n\t\t\tminimum = i\n\t\t}\n\t}\n\n\treturn minimum, maximum\n}\n\nfunc NewBool(b bool) *bool {\n\treturn &b\n}\n"
  },
  {
    "path": "main.go",
    "content": "/*\nCopyright © 2023 The Helm Compose Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\npackage main\n\nimport \"github.com/seacrew/helm-compose/cmd\"\n\nfunc main() {\n\tcmd.Execute()\n}\n"
  },
  {
    "path": "mkdocs.yaml",
    "content": "site_name: Helm Compose Documentation\ndocs_dir: docs\nrepo_url: https://github.com/seacrew/helm-compose\n\nnav:\n  - Home: \"index.md\"\n  - \"Quick Start\": \"quick-start.md\"\n  - \"Key Features and Use Cases\": \"key-features-and-use-cases.md\"\n  - \"Compose File Reference\": \"compose-file-reference.md\"\n  - \"Storage Providers\": \"storage-providers.md\"\n  - Commands:\n      - \"helm compose up\": \"commands/up.md\"\n      - \"helm compose down\": \"commands/down.md\"\n      - \"helm compose list\": \"commands/list.md\"\n      - \"helm compose get\": \"commands/get.md\"\n      - \"helm compose template\": \"commands/template.md\"\n\ntheme:\n  name: material\n  logo: https://user-images.githubusercontent.com/18513179/239762487-ec236277-f782-4da3-8a23-692ad017bb92.svg\n  favicon: https://user-images.githubusercontent.com/18513179/212496536-76db8b48-fe7c-42a3-b851-da1f281e1ad6.svg\n  palette:\n    - media: \"(prefers-color-scheme: light)\"\n      scheme: default\n      primary: custom\n      accent: custom\n      toggle:\n        icon: material/brightness-7\n        name: Switch to dark mode\n    - media: \"(prefers-color-scheme: dark)\"\n      scheme: slate\n      primary: custom\n      accent: custom\n      toggle:\n        icon: material/brightness-4\n        name: Switch to light mode\n  features:\n    - navigation.sections\n    - navigation.expand\n    - navigation.path\n    - navigation.indexes\n    - navigation.footer\n    - content.code.copy\n\nextra_css:\n  - stylesheets/extra.css\n\nplugins:\n  - search\n  - autolinks\n  - drawio_file\n  - git-revision-date-localized\n\nmarkdown_extensions:\n  - abbr\n  - tables\n  - pymdownx.highlight:\n      anchor_linenums: true\n      line_spans: __span\n      pygments_lang_class: true\n  - pymdownx.inlinehilite\n  - pymdownx.snippets\n  - pymdownx.superfences\n\nextra:\n  copyright: Copyright &copy; 2023 Seacrew Authors\n  social:\n    - icon: fontawesome/brands/github\n      link: https://github.com/seacrew\n  version:\n    provider: mike\n  consent:\n    title: Cookie consent\n    description: >-\n      We use cookies to recognize your repeated visits and preferences, as well\n      as to measure the effectiveness of our documentation and whether users\n      find what they're searching for. With your consent, you're helping us to\n      make our documentation better.\n"
  },
  {
    "path": "plugin.yaml",
    "content": "name: compose\nversion: 1.3.0\nusage: Compose is a helm plugin to define and manage multiple helm releases as single entity.\ncommand: $HELM_PLUGIN_DIR/bin/compose\nhooks:\n  install: $HELM_PLUGIN_DIR/scripts/install.sh\n  update: $HELM_PLUGIN_DIR/scripts/install.sh\n"
  },
  {
    "path": "scripts/install.sh",
    "content": "#!/usr/bin/env bash\n\nif [ \"${HELM_DEBUG:-}\" = \"1\" ] || [ \"${HELM_DEBUG:-}\" = \"true\" ] || [ -n \"${HELM_SECRETS_DEBUG+x}\" ]; then\n    set -x\nfi\n\nPLUGIN_NAME=\"helm-compose\"\nGITHUB_REPO=\"seacrew/helm-compose\"\n\n[ -z \"$HELM_BIN\" ] && HELM_BIN=$(command -v helm)\n\n[ -z \"$HELM_HOME\" ] && HELM_HOME=$(helm env | grep 'HELM_DATA_HOME' | cut -d '=' -f2 | tr -d '\"')\n\n# Convert HELM_BIN and HELM_PLUGIN_DIR to unix if cygpath is\n# available. This is the case when using MSYS2 or Cygwin\n# on Windows where helm returns a Windows path but we\n# need a Unix path\n\nif command -v cygpath >/dev/null 2>&1; then\n  HELM_BIN=\"$(cygpath -u \"${HELM_BIN}\")\"\n  HELM_PLUGIN_DIR=\"$(cygpath -u \"${HELM_PLUGIN_DIR}\")\"\nfi\n\nmkdir -p \"$HELM_HOME\"\n\n: \"${HELM_PLUGIN_DIR:=\"$HELM_HOME/plugins/helm-compose\"}\"\n\nif [[ $SKIP_BIN_INSTALL == \"1\" ]]; then\n  echo \"Skipping binary install\"\n  exit\nfi\n\n# which mode is the common installer script running in\nSCRIPT_MODE=\"install\"\nif [ \"$1\" = \"-u\" ]; then\n  SCRIPT_MODE=\"update\"\nfi\n\n# initArch discovers the architecture for this system.\ninitArch() {\n  ARCH=$(uname -m)\n  case $ARCH in\n    armv5*) ARCH=\"armv5\";;\n    armv6*) ARCH=\"armv6\";;\n    armv7*) ARCH=\"armv7\";;\n    aarch64) ARCH=\"arm64\";;\n    x86) ARCH=\"386\";;\n    x86_64) ARCH=\"amd64\";;\n    i686) ARCH=\"386\";;\n    i386) ARCH=\"386\";;\n  esac\n}\n\n# initOS discovers the operating system for this system.\ninitOS() {\n  OS=$(echo `uname`|tr '[:upper:]' '[:lower:]')\n\n  case \"$OS\" in\n    # Msys support\n    msys*) OS='windows';;\n    # Minimalist GNU for Windows\n    mingw*) OS='windows';;\n    darwin) OS='macos';;\n  esac\n}\n\n# verifySupported checks that the os/arch combination is supported for\n# binary builds.\nverifySupported() {\n  local supported=\"linux-amd64\\nlinux-arm64\\nfreebsd-amd64\\nmacos-amd64\\nmacos-arm64\\nwindows-amd64\"\n  if ! echo \"${supported}\" | grep -q \"${OS}-${ARCH}\"; then\n    echo \"No prebuild binary for ${OS}-${ARCH}.\"\n    exit 1\n  fi\n\n  if ! type \"curl\" > /dev/null && ! type \"wget\" > /dev/null; then\n    echo \"Either curl or wget is required\"\n    exit 1\n  fi\n}\n\n# getDownloadURL checks the latest available version.\ngetDownloadURL() {\n  version=$(git -C \"$HELM_PLUGIN_DIR\" describe --tags --exact-match 2>/dev/null || :)\n  if [ \"$SCRIPT_MODE\" = \"install\" ] && [ -n \"$version\" ]; then\n    DOWNLOAD_URL=\"https://github.com/$GITHUB_REPO/releases/download/$version/helm-compose-$OS-$ARCH.tgz\"\n  else\n    DOWNLOAD_URL=\"https://github.com/$GITHUB_REPO/releases/latest/download/helm-compose-$OS-$ARCH.tgz\"\n  fi\n}\n\n# downloadFile downloads the latest binary package and also the checksum\n# for that binary.\ndownloadFile() {\n  HELM_TMP=\"$(mktemp -d -t ${PLUGIN_NAME}-XXXXXX)\"\n  PLUGIN_TMP_FILE=\"${HELM_TMP}/${PLUGIN_NAME}.tgz\"\n  echo \"Downloading $DOWNLOAD_URL\"\n  if command -v curl >/dev/null 2>&1; then\n    curl -sSf -L \"$DOWNLOAD_URL\" >\"$PLUGIN_TMP_FILE\"\n  elif command -v wget >/dev/null 2>&1; then\n    wget -q -O - \"$DOWNLOAD_URL\" >\"$PLUGIN_TMP_FILE\"\n  fi\n}\n\n# installFile verifies the SHA256 for the file, then unpacks and\n# installs it.\ninstallFile() {\n  tar xzf \"$PLUGIN_TMP_FILE\" -C \"$HELM_TMP\"\n  HELM_TMP_BIN=\"$HELM_TMP/compose/bin/compose\"\n  if [ \"${OS}\" = \"windows\" ]; then\n    HELM_TMP_BIN=\"$HELM_TMP_BIN.exe\"\n  fi\n  echo \"Preparing to install into ${HELM_PLUGIN_DIR}\"\n  mkdir -p \"$HELM_PLUGIN_DIR/bin\"\n  cp \"$HELM_TMP_BIN\" \"$HELM_PLUGIN_DIR/bin\"\n}\n\n# fail_trap is executed if an error occurs.\nfail_trap() {\n  result=$?\n  if [ \"$result\" != \"0\" ]; then\n    echo \"Failed to install $PLUGIN_NAME\"\n    echo \"\\tFor support, go to https://github.com/$GITHUB_REPO/helm-compose.\"\n  fi\n  exit $result\n}\n\n# testVersion tests the installed client to make sure it is working.\ntestVersion() {\n  echo \"$PLUGIN_NAME installed into $HELM_PLUGIN_DIR\"\n  #\"${HELM_PLUGIN_DIR}/bin/compose\" -h\n}\n\n# Execution\n\n#Stop execution on any error\ntrap \"fail_trap\" EXIT\ninitArch\ninitOS\nverifySupported\ngetDownloadURL\ndownloadFile\ninstallFile\ntestVersion\n"
  }
]