[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug\ndescription: File a bug/issue\ntitle: \"[BUG] <title>\"\nlabels: [\"kind/bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: \"## Thank you for contributing to our Kompose!\"\n  - type: textarea\n    attributes:\n      label: Expected Behavior\n      description: |\n        Briefly describe what is the desired behavior.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Actual Behavior\n      description: |\n        Briefly describe what is the actual behavior.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Steps To Reproduce\n      description: Steps to reproduce the behavior.\n      placeholder: |\n        1. In this environment...\n        2. With this config...\n        3. Run '...'\n        4. See error or unexpected result...\n    validations:\n      required: false\n  - type: textarea\n    attributes:\n      label: Kompose Version\n      description: |\n        Paste output of `kompose version`.\n      render: Text\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Docker-Compose file\n      description: Paste output of the `docker-compose.yaml` that you are using.\n      render: YAML\n    validations:\n      required: false\n  - type: textarea\n    attributes:\n      label: Anything else?\n      description: |\n        Links? References? Anything that will give us more context about the issue you are encountering!\n\n        Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Kubernetes Community Slack\n    url: https://kubernetes.slack.com\n    about: \"Use the #kompose channel\"\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/enhancement.yml",
    "content": "name: Enhancement Tracking Issue\ndescription: Provide supporting details for a feature in development\nlabels: kind/feature\nbody:\n  - type: markdown\n    attributes:\n      value: \"## Thank you for contributing to our Kompose!\"\n  - type: textarea\n    id: feature\n    attributes:\n      label: What would you like to be added?\n      description: |\n        Describe what feature/enhancement that you want to be added to Kompose.\n    validations:\n      required: true\n\n  - type: textarea\n    id: rationale\n    attributes:\n      label: Why is this needed?\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "#### What type of PR is this?\n\n<!--\nAdd one of the following kinds:\n/kind bug\n/kind cleanup\n/kind documentation\n/kind feature\n-->\n\n#### What this PR does / why we need it:\n\n#### Which issue(s) this PR fixes:\n<!--\n*Automatically closes linked issue when PR is merged.\nUsage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.\n-->\nFixes #\n\n#### Special notes for your reviewer:\n"
  },
  {
    "path": ".github/dependabot.yaml",
    "content": "# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file\n\nversion: 2\n\nupdates:\n  - commit-message:\n      include: \"scope\"\n      prefix: \"chore(deps)\"\n    directory: \"/\"\n    open-pull-requests-limit: 10\n    package-ecosystem: \"gomod\"\n    schedule:\n      interval: \"daily\"\n\n  - commit-message:\n      include: \"scope\"\n      prefix: \"chore(ci)\"\n    directory: \"/\"\n    open-pull-requests-limit: 10\n    package-ecosystem: \"github-actions\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/workflows/go.yml",
    "content": "name: Go\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\nenv:\n  # Avoid noisy outputs like \"tput: No value for $TERM and no -T specified\"\n  TERM: dumb\n\njobs:\n\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    steps:\n\n    - name: Set up Go 1.x\n      uses: actions/setup-go@v5\n      with:\n        go-version: ^1.21\n      id: go\n\n    - name: Check out code into the Go module directory\n      uses: actions/checkout@v6\n\n    - name: Build\n      run: make bin\n\n    - name: Upload a Build Artifact\n      uses: actions/upload-artifact@v6\n      with:\n        name: \"kompose\"\n        path: \"kompose\"\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: lint\non:\n  pull_request:\njobs:\n  lint:\n    strategy:\n      matrix:\n        go: [1.21, 1.22]\n    name: lint\n    runs-on: ubuntu-latest\n    steps:\n      - name: \"Checkout\"\n        uses: actions/checkout@v6\n      - name: \"Install golang\"\n        uses: actions/setup-go@v5\n        with:\n          go-version: ${{ matrix.go }}\n      - name: \"Run go vet\"\n        run: \"go vet ./pkg/...\"\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Kompose CI\non:\n  push:\n    branches:\n      - main \n  pull_request:\nenv:\n  # Avoid noisy outputs like \"tput: No value for $TERM and no -T specified\"\n  TERM: dumb\njobs:\n  test:\n    name: Test with ${{ matrix.go }} and CROSS_COMPILE=${{ matrix.cross_compile }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        go: [1.21, 1.22]\n        cross_compile: [true, false]\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-go@v5\n        with:\n          go-version: ${{ matrix.go }}\n      - name: Install dyff\n        run: go install github.com/homeport/dyff/cmd/dyff@v1.5.8\n      - name: Run tests\n        run: make test\n      - name: Perform cross compile\n        if: ${{ matrix.cross_compile }}\n        run: make cross\n  docs:\n    name: Build docs and Coveralls integration\n    runs-on: ubuntu-latest\n    needs: test\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-go@v5\n        with:\n          go-version: ^1.21\n      - name: Install dyff\n        run: go install github.com/homeport/dyff/cmd/dyff@v1.5.8\n      - name: Create .coverprofile for each targeted directory by re:running tests\n        run: make test\n      - name: Collect all .coverprofile files and save it to one file gover.coverprofile\n        run: gover\n      - name: Send coverage\n        run: goveralls -coverprofile=gover.coverprofile -service=github\n        env:\n          # As per https://github.com/mattn/goveralls#github-actions\n          COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "#\n# KOMPOSE SPECIFIC\n#\n\n# Ignore compiled Kompose files\nkompose\nbin\n/docker-compose.yaml\n/docker-compose.yml\n/compose.yaml\n/compose.yml\nchanges.txt\n\n# Ignore site documents / when switching branches\ndocs/_site/\ndocs/.jekyll-cache/\ndocs/.git/\ndocs/.gitignore\n_site/\n.jekyll-cache/\n\n#\n# GO SPECIFIC\n#\n\n# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n*.test\n*.prof\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Coveralls files\n.coverprofile\n\n#\n# VIM SPECIFIC\n#\n\n# swap\n[._]*.s[a-w][a-z]\n[._]s[a-w][a-z]\n\n# session\nSession.vim\n\n# temporary\n.netrwhist\n*~\n\n# auto-generated tag files\ntags\n\n# IntelliJ IDE specific\n.idea\n\n.DS_Store\n\n# VSCode specific\n.vscode\n\n# Client Test generated files\nclient/testdata/generated\n\n\npkg/mod"
  },
  {
    "path": ".gitmodules",
    "content": ""
  },
  {
    "path": ".golangci.yml",
    "content": "# Golang CI pipeline configuration\nlinters:\n  disable-all: true\n\n  # Run golangci-lint.yml linters to see the list of all linters\n  # Please keep them sorted alphabetically\n  enable:\n    - bodyclose\n    - deadcode\n    - depguard\n#    - dogsled\n#    - errcheck\n#    - goconst\n    - goimports\n#    - staticcheck\n    - goprintffuncname\n#    - gosimple\n    - govet\n#    - ineffassign\n    - misspell\n#    - nakedret\n    - nolintlint\n    - rowserrcheck\n    - structcheck\n    - stylecheck\n    - typecheck\n    - unconvert\n    - varcheck\n    - whitespace\n"
  },
  {
    "path": ".mention-bot",
    "content": "{\n  \"maxReviewers\": 2,\n  \"numFilesToCheck\": 5,\n  \"message\": \"@pullRequester, thank you for the pull request! We'll request some people to review your PR. @reviewers, please review this.\",\n  \"fileBlacklist\": [\"*.md\"],\n  \"userBlacklist\": [\"ngtuna\", \"janetkuo\", \"sebgoa\", \"dustymabe\", \"gitlawr\"],\n  \"actions\": [\"opened\", \"labeled\"],\n  \"skipAlreadyMentionedPR\": true,\n  \"createReviewRequest\": true\n}\n"
  },
  {
    "path": ".openvex/templates/README.md",
    "content": "# OpenVEX Templates Directory\n\nThis directory contains the OpenVEX data for this repository.\nThe files stored in this directory are used as templates by\n`vexctl generate` when generating VEX data for a release or \na specific artifact.\n\nTo add new statements to publish data about a vulnerability,\ndownload [vexctl](https://github.com/openvex/vexctl)\nand append new statements using `vexctl add`. For example:\n```\nvexctl add --in-place main.openvex.json pkg:oci/test CVE-2014-1234567 fixed\n```\nThat will add a new VEX statement expressing that the impact of\nCVE-2014-1234567 is under investigation in the test image. When\ncutting a new release, for `pkg:oci/test` the new file will be\nincorporated to the relase's VEX data.\n\n## Read more about OpenVEX\n\nTo know more about generating, publishing and using VEX data\nin your project, please check out the vexctl repository and\ndocumentation: https://github.com/openvex/vexctl\n\nOpenVEX also has an examples repository with samples and docs:\nhttps://github.com/openvex/examples\n\n"
  },
  {
    "path": ".openvex/templates/main.openvex.json",
    "content": "{\n  \"@context\": \"https://openvex.dev/ns/v0.2.0\",\n  \"@id\": \"https://openvex.dev/docs/public/vex-6f9001fd8630edd2996df09f345882066d7b5bf512e54af918343d278640ecd0\",\n  \"author\": \"vexctl (automated template)\",\n  \"timestamp\": \"2023-12-15T19:10:43.910365Z\",\n  \"version\": 1,\n  \"statements\": []\n}\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "repos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v5.0.0\n    hooks:\n      - id: trailing-whitespace\n      - id: end-of-file-fixer\n      - id: check-added-large-files\n  - repo: https://github.com/dnephin/pre-commit-golang\n    rev: v0.5.1\n    hooks:\n      - id: go-fmt\n      - id: go-imports\n      - id: golangci-lint\n      - id: go-unit-tests\n  - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook\n    rev: v9.18.0\n    hooks:\n      - id: commitlint\n        stages: [commit-msg]\n        additional_dependencies: [\"@commitlint/config-conventional\"]\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing guidelines\n\n## How to become a contributor and submit your own code\n\n### Contributor License Agreements\n\nWe'd love to accept your patches! Before we can take them, we have to jump a couple of legal hurdles.\n\nPlease fill out either the individual or corporate Contributor License Agreement (CLA).\n\n- If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an individual CLA.\n- If you work for a company that wants to allow you to contribute your work, then you'll need to sign a corporate CLA.\n\nContact one of the [OWNERS](OWNERS) on Slack to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to accept your pull requests.\n\n### Contributing A Patch\n\n1. Submit an issue describing your proposed change to the repo in question.\n2. The [repo owners](OWNERS) will respond to your issue promptly.\n3. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above).\n4. Fork the desired repo, develop and test your code changes.\n5. Submit a pull request.\n\nNote: Code-related PR's require one ACK / LGTM from a maintainer or core contributor. Doc-related PR's require either one or none depending on the content changed (for example, a spec change would require one, but a spelling error would require none).\n\n### Adding dependencies\n\nIf your patch depends on new packages, make sure that both `go.mod` and `go.sum` are updated properly. Also we recommend you to execute `go mod tidy` before sending a pull request.\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Alpine Builder\nFROM alpine AS builder\n\nRUN apk add --no-cache curl\nCOPY ./build/VERSION VERSION\nRUN \\\n  version=$(cat VERSION) && \\\n  ARCH=$(uname -m | sed 's/armv7l/arm/g' | sed 's/aarch64/arm64/g' | sed 's/x86_64/amd64/g') && \\\n  curl -L \\\n    \"https://github.com/kubernetes/kompose/releases/download/v${version}/kompose-linux-${ARCH}\" \\\n    -o kompose && \\\n  chmod +x kompose\n\n# Runtime\nFROM alpine\n\nCOPY --from=builder /kompose /usr/bin/kompose\n"
  },
  {
    "path": "Jenkinsfile",
    "content": "@Library('github.com/fabric8io/fabric8-pipeline-library@master')\ndef dummy\ngoTemplate{\n  dockerNode{\n      goMake{\n        githubOrganisation = 'kubernetes'\n        dockerOrganisation = 'fabric8'\n        project = 'kompose'\n        makeCommand = \"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/usr/local/:/go/bin:/home/jenkins/go/bin \\\n                       && bash script/test/cmd/fix_detached_head.sh && make test\"\n      }\n  }\n}\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 {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.\n"
  },
  {
    "path": "Makefile",
    "content": "\n# Copyright 2016 The Kubernetes 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\n\nGITCOMMIT := $(shell git rev-parse --short HEAD)\nBUILD_FLAGS := -ldflags=\"-w -s -X github.com/kubernetes/kompose/pkg/version.GITCOMMIT=$(GITCOMMIT)\"\nTEST_IMAGE := kompose/tests:latest\n\n# go-get-tool will 'go get' any package $2 and install it to $1.\nPROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))\ndefine go-get-tool\n@[ -f $(1) ] || { \\\nset -e ;\\\nTMP_DIR=$$(mktemp -d) ;\\\ncd $$TMP_DIR ;\\\ngo mod init tmp ;\\\necho \"Downloading $(2)\" ;\\\nGOBIN=$(PROJECT_DIR)/bin go get $(2) ;\\\nrm -rf $$TMP_DIR ;\\\n}\nendef\n\ndefault: bin\n\n.PHONY: all\nall: bin\n\n.PHONY: bin\nbin:\n\tCGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -o kompose main.go\n\n.PHONY: install\ninstall:\n\tgo install ${BUILD_FLAGS}\n\n# kompile kompose for multiple platforms\n.PHONY: cross\ncross:\n\tGOOS=linux GOARCH=amd64 CGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -installsuffix cgo  -o \"bin/kompose-linux-amd64\" main.go\n\tGOOS=linux GOARCH=arm CGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -installsuffix cgo  -o \"bin/kompose-linux-arm\" main.go\n\tGOOS=linux GOARCH=arm64 CGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -installsuffix cgo  -o \"bin/kompose-linux-arm64\" main.go\n\tGOOS=windows GOARCH=amd64 CGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -installsuffix cgo  -o \"bin/kompose-windows-amd64.exe\" main.go\n\tGOOS=darwin GOARCH=amd64 CGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -installsuffix cgo  -o \"bin/kompose-darwin-amd64\" main.go\n\tGOOS=darwin GOARCH=arm64 CGO_ENABLED=0 GO111MODULE=on go build  ${BUILD_FLAGS} -installsuffix cgo  -o \"bin/kompose-darwin-arm64\" main.go\n\n.PHONY: clean\nclean:\n\trm -f kompose\n\trm -r -f bundles\n\n.PHONY: test-unit\ntest-unit:\n\tgo test -short $(BUILD_FLAGS) -race -cover -v ./...\n\n# Run unit tests and collect coverage\n.PHONY: test-unit-cover\ntest-unit-cover:\n\t# First install packages that are dependencies of the test.\n\tgo test -short -i -race -cover ./...\n\t# go test doesn't support colleting coverage across multiple packages,\n\t# generate go test commands using go list and run go test for every package separately\n\tgo list -f '\"go test -short -race -cover -v -coverprofile={{.Dir}}/.coverprofile {{.ImportPath}}\"' github.com/kubernetes/kompose/...  | grep -v \"vendor\" | xargs -L 1 -P4 sh -c\n\n\n# run openshift up/down tests\n.PHONY: test-openshift\ntest-openshift:\n\t./script/test_in_openshift/run.sh\n\n# run commandline tests\n.PHONY: test-cmd\ntest-cmd:\n\t./script/test/cmd/tests.sh\n\n# run all validation tests\n.PHONY: validate\nvalidate: gofmt vet\n\n.PHONY: vet\nvet:\n\tgo vet ./pkg/...\n\n.PHONY: gofmt\ngofmt:\n\t./script/check-gofmt.sh\n\n# Run all tests\n.PHONY: test\ntest: bin test-dep  validate test-unit-cover install test-cmd\n\n# Install all the required test-dependencies before executing tests (only valid when running `make test`)\n.PHONY: test-dep\ntest-dep:\n\tgo install github.com/mattn/goveralls@latest\n\tgo install github.com/modocache/gover@latest\n\tgo install github.com/mitchellh/gox@latest\n\n\n# build docker image that is used for running all test locally\n.PHONY: test-image\ntest-image:\n\tdocker build -t $(TEST_IMAGE) -f script/test_in_container/Dockerfile script/test_in_container/\n\n# run all test locally in docker image (image can be build by by build-test-image target)\n.PHONY: test-container\ntest-container:\n\tdocker run -v `pwd`:/opt/tmp/kompose:ro -it $(TEST_IMAGE)\n\n\n.PHONY: test-k8s\ntest-k8s:\n\t./script/test_k8s/test.sh\n\nGOLANGCI_LINT = $(shell pwd)/bin/golangci-lint\n.PHONY: install-golangci-lint\ninstall-golangci-lint:\n# golangci-lint version must consistent with github CI\n# ref: ./.github/workflows/golangci-lint.yml\n\t$(call go-get-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.32.2)\n\n.PHONY: golangci-lint\ngolangci-lint: install-golangci-lint\n\t$(GOLANGCI_LINT) run -c .golangci.yml --timeout 5m\n\n.PHONY: test-client\ntest-client: \n\tgo test ./client/...\n"
  },
  {
    "path": "OWNERS",
    "content": "# See the OWNERS file documentation:\n# https://github.com/kubernetes/community/blob/master/contributors/devel/owners.md\n\nreviewers:\n  - cdrage\n  - hangyan\n  - TessaIO\n\napprovers:\n  - cdrage\n  - hangyan\n  - TessaIO\n"
  },
  {
    "path": "README.md",
    "content": "# Kompose (Kubernetes + Compose)\n\n[![Build Status Widget]][Build Status] [![Coverage Status Widget]][Coverage Status] [![GoDoc Widget]][GoDoc]  [![GoReportCard Widget]][GoReportCardResult]\n\n![logo](/docs/assets/images/logo.png)\n\n`kompose` is a tool to help users who are familiar with `docker-compose` move to [Kubernetes](http://kubernetes.io). `kompose` takes a [Compose Specification](https://compose-spec.io/) file and translates it into Kubernetes resources.\n\n`kompose` is a convenience tool to go from local Compose environment to managing your application with Kubernetes. Transformation of the [Compose Specification](https://compose-spec.io/) format to Kubernetes resources manifest may not be exact, but it helps tremendously when first deploying an application on Kubernetes.\n\n## Use Case\n\nConvert [`compose.yaml`](https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml) into Kubernetes deployments and services with one simple command:\n\n```sh\n$ kompose convert -f compose.yaml\nINFO Kubernetes file \"frontend-service.yaml\" created\nINFO Kubernetes file \"redis-leader-service.yaml\" created\nINFO Kubernetes file \"redis-replica-service.yaml\" created\nINFO Kubernetes file \"frontend-deployment.yaml\" created\nINFO Kubernetes file \"redis-leader-deployment.yaml\" created\nINFO Kubernetes file \"redis-replica-deployment.yaml\" created\n```\n\nOther examples are provided in the _examples_ [directory](./examples).\n\n## Installation\n\nWe have multiple ways to install Kompose. Our preferred method is downloading the binary from the latest GitHub release.\n\nOur entire list of installation methods are located in our [installation.md](/docs/installation.md) document.\n\nInstallation methods:\n\n- [Binary (Preferred method)](/docs/installation.md#github-release)\n- [Go](/docs/installation.md#go)\n- [CentOS](/docs/installation.md#centos)\n- [openSUSE/SLE](/docs/installation.md#opensusesle)\n- [NixOS](/docs/installation.md#nixos)\n- [macOS (Homebrew and MacPorts)](/docs/installation.md#macos)\n- [Windows](/docs/installation.md#windows)\n- [Docker](/docs/installation.md#docker)\n\n#### Binary installation\n\nKompose is released via GitHub on a three-week cycle, you can see all current releases on the [GitHub release page](https://github.com/kubernetes/kompose/releases).\n\n**Linux and macOS:**\n\n```sh\n# Linux\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-linux-amd64 -o kompose\n\n# macOS\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-darwin-amd64 -o kompose\n\nchmod +x kompose\nsudo mv ./kompose /usr/local/bin/kompose\n```\n\n**Windows:**\n\nDownload from [GitHub](https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-windows-amd64.exe) and add the binary to your PATH.\n\n## Shell autocompletion\n\nWe support Bash, Zsh and Fish autocompletion.\n\n```sh\n# Bash (add to .bashrc for persistence)\nsource <(kompose completion bash)\n\n# Zsh (add to .zshrc for persistence)\nsource <(kompose completion zsh)\n\n# Fish autocompletion\nkompose completion fish | source\n```\n\n## Development and building of Kompose\n\n### Building with `go`\n\n**Requisites:**\n\n1. [make](https://www.gnu.org/software/make/)\n2. [Golang](https://golang.org/) v1.6 or later\n3. Set `GOPATH` correctly or click [SettingGOPATH](https://github.com/golang/go/wiki/SettingGOPATH) for details\n\n**Steps:**\n\n1. Clone repository\n\n```console\n$ git clone https://github.com/kubernetes/kompose.git $GOPATH/src/github.com/kubernetes/kompose\n```\n\n2. Change directory to the cloned repo.\n\n```console\ncd $GOPATH/src/github.com/kubernetes/kompose\n```\n\n3. Build with `make`\n\n```console\n$ make bin\n```\n\n4. Or build with `go`\n\n```console\n$ go build -o kompose main.go\n```\n\n5. Test your changes\n\n```console\n$ make test\n```\n\n## Documentation\n\nDocumentation can be found at our [kompose.io](http://kompose.io) website or our [docs](https://github.com/kubernetes/kompose/tree/main/docs) folder.\n\nHere is a list of all available docs:\n\n- [Quick start](docs/getting-started.md)\n- [Installation](docs/installation.md)\n- [User guide](docs/user-guide.md)\n- [Conversion](docs/conversion.md)\n- [Architecture](docs/architecture.md)\n- [Development](docs/development.md)\n\n## Community, Discussion, Contribution, and Support\n\n**Issues:** If you find any issues, please [file it](https://github.com/kubernetes/kompose/issues).\n\n**Kubernetes Community:** As part of the Kubernetes ecosystem, we follow the Kubernetes community principles. More information can be found on the [community page](http://kubernetes.io/community/).\n\n**Chat (Slack):** We're fairly active on [Slack](http://slack.kubernetes.io#kompose) and you can find us in the #kompose channel.\n\n### Code of Conduct\n\nParticipation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md).\n\n[Build Status]: https://github.com/kubernetes/kompose/actions?query=workflow%3A%22Kompose+CI%22\n[Build Status Widget]: https://github.com/kubernetes/kompose/workflows/Kompose%20CI/badge.svg\n[GoDoc]: https://godoc.org/github.com/kubernetes/kompose\n[GoDoc Widget]: https://godoc.org/github.com/kubernetes/kompose?status.svg\n[Coverage Status Widget]: https://coveralls.io/repos/github/kubernetes/kompose/badge.svg?branch=main\n[Coverage Status]: https://coveralls.io/github/kubernetes/kompose?branch=main\n[GoReportCard Widget]: https://goreportcard.com/badge/github.com/kubernetes/kompose\n[GoReportCardResult]: https://goreportcard.com/report/github.com/kubernetes/kompose\n"
  },
  {
    "path": "RELEASE.md",
    "content": "# Release Process\n\nThe process is as follows:\n\n1. A PR proposing a new release with a changelog since the last release\n1. At least 2 or more [OWNERS](OWNERS) must LGTM this release\n1. The release PR is closed\n1. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION`\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Security Announcements\n\nJoin the [kubernetes-security-announce] group for security and vulnerability announcements.\n\nYou can also subscribe to an RSS feed of the above using [this link][kubernetes-security-announce-rss].\n\n## Reporting a Vulnerability\n\nInstructions for reporting a vulnerability can be found on the\n[Kubernetes Security and Disclosure Information] page.\n\n## Supported Versions\n\nInformation about supported Kubernetes versions can be found on the\n[Kubernetes version and version skew support policy] page on the Kubernetes website.\n\n[kubernetes-security-announce]: https://groups.google.com/forum/#!forum/kubernetes-security-announce\n[kubernetes-security-announce-rss]: https://groups.google.com/forum/feed/kubernetes-security-announce/msgs/rss_v2_0.xml?num=50\n[Kubernetes version and version skew support policy]: https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions\n[Kubernetes Security and Disclosure Information]: https://kubernetes.io/docs/reference/issues-security/security/#report-a-vulnerability\n"
  },
  {
    "path": "SECURITY_CONTACTS",
    "content": "# Defined below are the security contacts for this repo.\n#\n# They are the contact point for the Product Security Committee to reach out\n# to for triaging and handling of incoming issues.\n#\n# The below names agree to abide by the\n# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy)\n# and will be removed and replaced if they violate that agreement.\n#\n# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE\n# INSTRUCTIONS AT https://kubernetes.io/security/\n\ncdrage\nkadel\nhangyan\njanetkuo\nngtuna\nsebgoa\nAhmedGrati\n"
  },
  {
    "path": "build/README.md",
    "content": "# Fedora RPM packaging\n\nThere are instructions on how to build the RPM.\n\n# 1. Gofed\n\nGrab gofed from https://github.com/gofed/gofed\n\nChoose which version of the repo you want to build. For kompose it was 0.3.0 and the commit was 135165b39c55d29a5426479ded81eddd56bfbaf4\n\nRun the following to generate spec file:\n\n```sh\ngofed repo2spec --detect github.com/kubernetes/kompose --commit 135165b39c55d29a5426479ded81eddd56bfbaf4 --with-extra --with-build -f\n```\n\nThe spec file is now located at:\n\n```sh\n$HOME/gofed/golang-github-kubernetes-incubator-kompose/golang-github-kubernetes-incubator-kompose.spec\n```\n\n# 2. Dependencies\n\nNow we need to go through and fix some things.\n\nGenerate bundled dependencies by using parsedeps.go\n\nGo to the kompose source folder and then run:\n\n```sh\ngo run parsedeps.go\n```\n\nIn the future this will possibly done by `gofed`, see: https://github.com/gofed/gofed/issues/42\n\n# 3. Building a source RPM locally on CentOS\n\nFirst, follow instructions to do local setup https://wiki.centos.org/HowTos/SetupRpmBuildEnvironment\n\nSource: https://wiki.centos.org/HowTos/RebuildSRPM\n\nSecond, checkout the source to the release commit\n\nCopy the kompose code directory with name `kompose-135165b39c55d29a5426479ded81eddd56bfbaf4`\n\nTar the `kompose-135165b39c55d29a5426479ded81eddd56bfbaf4` code directory as `kompose-135165b.tar.gz` and copy it to `$HOME/rpmbuild/SOURCES/`\n\nRun following command:\n\n```sh\nrpmbuild -ba kompose.spec\n```\n\nFind the srpm in `$HOME/rpmbuild/SRPMS`\n\nFind the RPM in `$HOME/rpmbuild/RPM/arch/`\n\nCheck that the dependencies are proper:\n\n```sh\nrpm -qpR RPMS/x86_64/kompose-0.3.0-0.1.git135165b.el7.centos.x86_64.rpm\n```\n\n# 4. Running in on Koji (build system)\n\nFirst, setup your environment in order to run Koji: https://fedoraproject.org/wiki/Using_the_Koji_build_system\n\nExample setup:\n\n```sh\nfedora-packager-setup\nkinit <username>@FEDORAPROJECT.ORG\n```\n\nTo build it on koji run:\n\n```\nkoji build --scratch rawhide kompose-0.3.0-0.1.git135165b.el7.centos.src.rpm\n```\n"
  },
  {
    "path": "build/VERSION",
    "content": "1.38.0\n"
  },
  {
    "path": "client/client.go",
    "content": "package client\n\ntype Kompose struct {\n\tsuppressWarnings bool\n\tverbose          bool\n\terrorOnWarning   bool\n}\n\nfunc NewClient(opts ...Opt) (*Kompose, error) {\n\tk := &Kompose{\n\t\tsuppressWarnings: false,\n\t\tverbose:          false,\n\t\terrorOnWarning:   false,\n\t}\n\tfor _, op := range opts {\n\t\tif err := op(k); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn k, nil\n}\n"
  },
  {
    "path": "client/convert.go",
    "content": "package client\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/kubernetes/kompose/pkg/app\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\nfunc (k *Kompose) Convert(options ConvertOptions) ([]runtime.Object, error) {\n\toptions = k.setDefaultValues(options)\n\terr := k.validateOptions(options)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tkobjectConvertOptions := kobject.ConvertOptions{\n\t\tToStdout:                    options.ToStdout,\n\t\tCreateChart:                 k.createChart(options),\n\t\tGenerateYaml:                true,\n\t\tGenerateJSON:                options.GenerateJson,\n\t\tReplicas:                    *options.Replicas,\n\t\tInputFiles:                  options.InputFiles,\n\t\tOutFile:                     options.OutFile,\n\t\tProvider:                    k.getProvider(options),\n\t\tCreateD:                     k.createDeployment(options),\n\t\tCreateDS:                    k.createDaemonSet(options),\n\t\tCreateRC:                    k.createReplicationController(options),\n\t\tBuild:                       *options.Build,\n\t\tBuildRepo:                   k.buildRepo(options),\n\t\tBuildBranch:                 k.buildBranch(options),\n\t\tPushImage:                   options.PushImage,\n\t\tPushImageRegistry:           options.PushImageRegistry,\n\t\tCreateDeploymentConfig:      k.createDeploymentConfig(options),\n\t\tEmptyVols:                   false,\n\t\tProfiles:                    options.Profiles,\n\t\tVolumes:                     *options.VolumeType,\n\t\tPVCRequestSize:              options.PvcRequestSize,\n\t\tInsecureRepository:          k.insecureRepository(options),\n\t\tIsDeploymentFlag:            k.createDeployment(options),\n\t\tIsDaemonSetFlag:             k.createDaemonSet(options),\n\t\tIsReplicationControllerFlag: k.createReplicationController(options),\n\t\tController:                  k.getController(options),\n\t\tIsReplicaSetFlag:            *options.Replicas != 0,\n\t\tIsDeploymentConfigFlag:      k.createDeploymentConfig(options),\n\t\tYAMLIndent:                  2,\n\t\tWithKomposeAnnotation:       *options.WithKomposeAnnotations,\n\t\tMultipleContainerMode:       k.multiContainerMode(options),\n\t\tServiceGroupMode:            k.serviceGroupMode(options),\n\t\tServiceGroupName:            k.serviceGroupName(options),\n\t\tSecretsAsFiles:              k.secretsAsFiles(options),\n\t\tGenerateNetworkPolicies:     options.GenerateNetworkPolicies,\n\t}\n\terr = app.ValidateComposeFile(&kobjectConvertOptions)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tobjects, err := app.Convert(kobjectConvertOptions)\n\treturn objects, err\n}\n\nfunc (k *Kompose) setDefaultValues(options ConvertOptions) ConvertOptions {\n\treplicasDefaultValue := 1\n\tbuildDefaultValue := \"none\"\n\tvolumeTypeDefaultValue := \"persistentVolumeClaim\"\n\twithKomposeAnnotationsDefaultValue := true\n\tkubernetesControllerDefaultValue := \"\"\n\tkubernetesServiceGroupModeDefaultValue := \"\"\n\n\tif options.Replicas == nil {\n\t\toptions.Replicas = &replicasDefaultValue\n\t}\n\tif options.Build == nil {\n\t\toptions.Build = &buildDefaultValue\n\t}\n\tif options.VolumeType == nil {\n\t\toptions.VolumeType = &volumeTypeDefaultValue\n\t}\n\tif options.WithKomposeAnnotations == nil {\n\t\toptions.WithKomposeAnnotations = &withKomposeAnnotationsDefaultValue\n\t}\n\tif options.Provider == nil {\n\t\toptions.Provider = Kubernetes{\n\t\t\tController: &kubernetesControllerDefaultValue,\n\t\t}\n\t}\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\tif kubernetesProvider.Controller == nil {\n\t\t\toptions.Provider = Kubernetes{\n\t\t\t\tController:         &kubernetesControllerDefaultValue,\n\t\t\t\tChart:              options.Provider.(Kubernetes).Chart,\n\t\t\t\tMultiContainerMode: options.Provider.(Kubernetes).MultiContainerMode,\n\t\t\t\tServiceGroupMode:   options.Provider.(Kubernetes).ServiceGroupMode,\n\t\t\t\tServiceGroupName:   options.Provider.(Kubernetes).ServiceGroupName,\n\t\t\t\tSecretsAsFiles:     options.Provider.(Kubernetes).SecretsAsFiles,\n\t\t\t}\n\t\t}\n\t\tif kubernetesProvider.ServiceGroupMode == nil {\n\t\t\toptions.Provider = Kubernetes{\n\t\t\t\tController:         options.Provider.(Kubernetes).Controller,\n\t\t\t\tChart:              options.Provider.(Kubernetes).Chart,\n\t\t\t\tMultiContainerMode: options.Provider.(Kubernetes).MultiContainerMode,\n\t\t\t\tServiceGroupMode:   &kubernetesServiceGroupModeDefaultValue,\n\t\t\t\tServiceGroupName:   options.Provider.(Kubernetes).ServiceGroupName,\n\t\t\t\tSecretsAsFiles:     options.Provider.(Kubernetes).SecretsAsFiles,\n\t\t\t}\n\t\t}\n\t}\n\treturn options\n}\n\nfunc (k *Kompose) validateOptions(options ConvertOptions) error {\n\tbuild := options.Build\n\tif *build != string(LOCAL) && *build != string(BUILD_CONFIG) && *build != string(NONE) {\n\t\treturn fmt.Errorf(\n\t\t\t\"unexpected Value for Build field. Possible values are: %v, %v, and %v\", string(LOCAL), string(BUILD_CONFIG), string(NONE),\n\t\t)\n\t}\n\n\tvolumeType := options.VolumeType\n\tif *volumeType != string(PVC) && *volumeType != string(EMPTYDIR) && *volumeType != string(HOSTPATH) && *volumeType != string(CONFIGMAP) {\n\t\treturn fmt.Errorf(\n\t\t\t\"unexpected Value for VolumeType field. Possible values are: %v, %v, %v, %v\", string(PVC), string(EMPTYDIR), string(HOSTPATH), string(CONFIGMAP),\n\t\t)\n\t}\n\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\tkubernetesController := kubernetesProvider.Controller\n\t\tif *kubernetesController != \"\" && *kubernetesController != string(DEPLOYMENT) && *kubernetesController != string(DAEMONSET) && *kubernetesController != string(REPLICATION_CONTROLLER) {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"unexpected Value for Kubernetes Controller field. Possible values are: %v, %v, and %v\", string(DEPLOYMENT), string(DAEMONSET), string(REPLICATION_CONTROLLER),\n\t\t\t)\n\t\t}\n\n\t\tkubernetesServiceGroupMode := kubernetesProvider.ServiceGroupMode\n\t\tif *kubernetesServiceGroupMode != string(LABEL) && *kubernetesServiceGroupMode != string(VOLUME) && *kubernetesServiceGroupMode != \"\" {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"unexpected Value for Kubernetes Service Groupe Mode field. Possible values are: %v, %v, ''\", string(LABEL), string(VOLUME),\n\t\t\t)\n\t\t}\n\n\t\tif *build == string(BUILD_CONFIG) {\n\t\t\treturn fmt.Errorf(\"the build value %v is only supported for Openshift provider\", string(BUILD_CONFIG))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (k *Kompose) createDeployment(options ConvertOptions) bool {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn *kubernetesProvider.Controller == string(DEPLOYMENT)\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) createDaemonSet(options ConvertOptions) bool {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn *kubernetesProvider.Controller == string(DAEMONSET)\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) createReplicationController(options ConvertOptions) bool {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn *kubernetesProvider.Controller == string(REPLICATION_CONTROLLER)\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) createChart(options ConvertOptions) bool {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn kubernetesProvider.Chart\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) multiContainerMode(options ConvertOptions) bool {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn kubernetesProvider.MultiContainerMode\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) serviceGroupMode(options ConvertOptions) string {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn *kubernetesProvider.ServiceGroupMode\n\t}\n\treturn \"\"\n}\n\nfunc (k *Kompose) serviceGroupName(options ConvertOptions) string {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn kubernetesProvider.ServiceGroupName\n\t}\n\treturn \"\"\n}\n\nfunc (k *Kompose) secretsAsFiles(options ConvertOptions) bool {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn kubernetesProvider.SecretsAsFiles\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) createDeploymentConfig(options ConvertOptions) bool {\n\tif _, ok := options.Provider.(Openshift); ok {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) insecureRepository(options ConvertOptions) bool {\n\tif openshiftProvider, ok := options.Provider.(Openshift); ok {\n\t\treturn openshiftProvider.InsecureRepository\n\t}\n\treturn false\n}\n\nfunc (k *Kompose) buildRepo(options ConvertOptions) string {\n\tif openshiftProvider, ok := options.Provider.(Openshift); ok {\n\t\treturn openshiftProvider.BuildRepo\n\t}\n\treturn \"\"\n}\n\nfunc (k *Kompose) buildBranch(options ConvertOptions) string {\n\tif openshiftProvider, ok := options.Provider.(Openshift); ok {\n\t\treturn openshiftProvider.BuildRepo\n\t}\n\treturn \"\"\n}\n\nfunc (k *Kompose) getProvider(options ConvertOptions) string {\n\tif _, ok := options.Provider.(Openshift); ok {\n\t\treturn \"openshift\"\n\t}\n\tif _, ok := options.Provider.(Kubernetes); ok {\n\t\treturn \"kubernetes\"\n\t}\n\treturn \"kubernetes\"\n}\n\nfunc (k *Kompose) getController(options ConvertOptions) string {\n\tif kubernetesProvider, ok := options.Provider.(Kubernetes); ok {\n\t\treturn *kubernetesProvider.Controller\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "client/convert_test.go",
    "content": "package client\n\nimport (\n\t\"fmt\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"gotest.tools/v3/assert\"\n\tis \"gotest.tools/v3/assert/cmp\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n)\n\nfunc TestConvertError(t *testing.T) {\n\trandomBuildValue := \"random-build\"\n\trandomVolumeTypeValue := \"random-volume-type\"\n\trandomKubernetesControllerValue := \"random-controller\"\n\trandomKubernetesServiceGroupModeValue := \"random-group-mode\"\n\tbuildConfigValue := string(BUILD_CONFIG)\n\ttestCases := []struct {\n\t\toptions      ConvertOptions\n\t\terrorMessage string\n\t}{\n\t\t{\n\t\t\toptions: ConvertOptions{\n\t\t\t\tBuild: &randomBuildValue,\n\t\t\t},\n\t\t\terrorMessage: fmt.Sprintf(\"unexpected Value for Build field. Possible values are: %v, %v, and %v\", string(LOCAL), string(BUILD_CONFIG), string(NONE)),\n\t\t},\n\t\t{\n\t\t\toptions: ConvertOptions{\n\t\t\t\tVolumeType: &randomVolumeTypeValue,\n\t\t\t},\n\t\t\terrorMessage: fmt.Sprintf(\"unexpected Value for VolumeType field. Possible values are: %v, %v, %v, %v\", string(PVC), string(EMPTYDIR), string(HOSTPATH), string(CONFIGMAP)),\n\t\t},\n\t\t{\n\t\t\toptions: ConvertOptions{\n\t\t\t\tProvider: Kubernetes{\n\t\t\t\t\tController: &randomKubernetesControllerValue,\n\t\t\t\t},\n\t\t\t},\n\t\t\terrorMessage: fmt.Sprintf(\"unexpected Value for Kubernetes Controller field. Possible values are: %v, %v, and %v\", string(DEPLOYMENT), string(DAEMONSET), string(REPLICATION_CONTROLLER)),\n\t\t},\n\t\t{\n\t\t\toptions: ConvertOptions{\n\t\t\t\tProvider: Kubernetes{\n\t\t\t\t\tServiceGroupMode: &randomKubernetesServiceGroupModeValue,\n\t\t\t\t},\n\t\t\t},\n\t\t\terrorMessage: fmt.Sprintf(\"unexpected Value for Kubernetes Service Groupe Mode field. Possible values are: %v, %v, ''\", string(LABEL), string(VOLUME)),\n\t\t},\n\t\t{\n\t\t\toptions: ConvertOptions{\n\t\t\t\tProvider: Kubernetes{},\n\t\t\t\tBuild:    &buildConfigValue,\n\t\t\t},\n\t\t\terrorMessage: fmt.Sprintf(\"the build value %v is only supported for Openshift provider\", string(BUILD_CONFIG)),\n\t\t},\n\t}\n\n\tclient, err := NewClient()\n\tassert.Check(t, is.Equal(err, nil))\n\tfor _, tc := range testCases {\n\t\t_, err := client.Convert(tc.options)\n\n\t\tassert.Check(t, is.Equal(err.Error(), tc.errorMessage))\n\t}\n}\n\nfunc TestConvertWithDefaultOptions(t *testing.T) {\n\tclient, err := NewClient(WithErrorOnWarning())\n\tassert.Check(t, is.Equal(err, nil))\n\tobjects, err := client.Convert(ConvertOptions{\n\t\tToStdout: true,\n\t\tInputFiles: []string{\n\t\t\t\"./testdata/docker-compose.yaml\",\n\t\t},\n\t})\n\tassert.Check(t, is.Equal(err, nil))\n\tfor _, object := range objects {\n\t\tif deployment, ok := object.(*appsv1.Deployment); ok {\n\t\t\tassert.Check(t, is.Equal(int(*deployment.Spec.Replicas), 1))\n\t\t}\n\t}\n}\n\nfunc TestConvertWithProfiles(t *testing.T) {\n\tclient, err := NewClient(WithErrorOnWarning())\n\tassert.Check(t, is.Equal(err, nil))\n\n\ttype Want struct {\n\t\tdeploymentsNames []string\n\t\tservicesNames    []string\n\t}\n\n\ttests := []struct {\n\t\tname    string\n\t\toptions ConvertOptions\n\t\twant    Want\n\t}{\n\t\t{\n\t\t\tname: \"No profiles provided\",\n\t\t\toptions: ConvertOptions{\n\t\t\t\tToStdout: true,\n\t\t\t\tInputFiles: []string{\n\t\t\t\t\t\"./testdata/docker-compose-profiles.yaml\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: Want{\n\t\t\t\tdeploymentsNames: nil,\n\t\t\t\tservicesNames:    nil,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"All profiles provided\",\n\t\t\toptions: ConvertOptions{\n\t\t\t\tToStdout: true,\n\t\t\t\tInputFiles: []string{\n\t\t\t\t\t\"./testdata/docker-compose-profiles.yaml\",\n\t\t\t\t},\n\t\t\t\tProfiles: []string{\"hello\", \"world\"},\n\t\t\t},\n\t\t\twant: Want{\n\t\t\t\tdeploymentsNames: []string{\"backend\", \"frontend\", \"database\"},\n\t\t\t\tservicesNames:    []string{\"backend\", \"frontend\", \"database\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"One profile only\",\n\t\t\toptions: ConvertOptions{\n\t\t\t\tToStdout: true,\n\t\t\t\tInputFiles: []string{\n\t\t\t\t\t\"./testdata/docker-compose-profiles.yaml\",\n\t\t\t\t},\n\t\t\t\tProfiles: []string{\"hello\"},\n\t\t\t},\n\t\t\twant: Want{\n\t\t\t\tdeploymentsNames: []string{\"backend\", \"frontend\"},\n\t\t\t\tservicesNames:    []string{\"backend\", \"frontend\"},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tobjects, err := client.Convert(tt.options)\n\t\t\tassert.Check(t, is.Equal(err, nil))\n\n\t\t\tsort.Strings(tt.want.deploymentsNames)\n\t\t\tsort.Strings(tt.want.servicesNames)\n\n\t\t\tvar deploymentsNames []string\n\t\t\tvar servicesNames []string\n\n\t\t\tfor _, object := range objects {\n\t\t\t\tif deployment, ok := object.(*appsv1.Deployment); ok {\n\t\t\t\t\tdeploymentsNames = append(deploymentsNames, deployment.Name)\n\t\t\t\t}\n\n\t\t\t\tif service, ok := object.(*v1.Service); ok {\n\t\t\t\t\tservicesNames = append(servicesNames, service.Name)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsort.Strings(deploymentsNames)\n\t\t\tsort.Strings(servicesNames)\n\n\t\t\tassert.Check(t, is.DeepEqual(deploymentsNames, tt.want.deploymentsNames))\n\t\t\tassert.Check(t, is.DeepEqual(servicesNames, tt.want.servicesNames))\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "client/options.go",
    "content": "package client\n\n// Opt is a configuration option to initialize a client\ntype Opt func(*Kompose) error\n\nfunc WithSuppressWarnings() Opt {\n\treturn func(k *Kompose) error {\n\t\tk.suppressWarnings = true\n\t\treturn nil\n\t}\n}\n\nfunc WithVerboseOutput() Opt {\n\treturn func(k *Kompose) error {\n\t\tk.verbose = true\n\t\treturn nil\n\t}\n}\n\nfunc WithErrorOnWarning() Opt {\n\treturn func(k *Kompose) error {\n\t\tk.errorOnWarning = true\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "client/options_test.go",
    "content": "package client\n\nimport (\n\t\"testing\"\n\n\t\"gotest.tools/v3/assert\"\n\tis \"gotest.tools/v3/assert/cmp\"\n)\n\nfunc TestNewClientWithOpts(t *testing.T) {\n\ttestCases := []struct {\n\t\texpectedError            error\n\t\texpectedSuppressWarnings bool\n\t\texpectedVerbose          bool\n\t\texpectedErrorOnWarnings  bool\n\t\topts                     []Opt\n\t}{\n\t\t{\n\t\t\texpectedError:            nil,\n\t\t\texpectedSuppressWarnings: false,\n\t\t\texpectedVerbose:          false,\n\t\t\texpectedErrorOnWarnings:  false,\n\t\t\topts:                     []Opt{},\n\t\t},\n\t\t{\n\t\t\texpectedError:            nil,\n\t\t\texpectedSuppressWarnings: true,\n\t\t\texpectedVerbose:          false,\n\t\t\texpectedErrorOnWarnings:  false,\n\t\t\topts:                     []Opt{WithSuppressWarnings()},\n\t\t},\n\t\t{\n\t\t\texpectedError:            nil,\n\t\t\texpectedSuppressWarnings: false,\n\t\t\texpectedVerbose:          true,\n\t\t\texpectedErrorOnWarnings:  false,\n\t\t\topts:                     []Opt{WithVerboseOutput()},\n\t\t},\n\t\t{\n\t\t\texpectedError:            nil,\n\t\t\texpectedSuppressWarnings: false,\n\t\t\texpectedVerbose:          false,\n\t\t\texpectedErrorOnWarnings:  true,\n\t\t\topts:                     []Opt{WithErrorOnWarning()},\n\t\t},\n\t\t{\n\t\t\texpectedError:            nil,\n\t\t\texpectedSuppressWarnings: true,\n\t\t\texpectedVerbose:          false,\n\t\t\texpectedErrorOnWarnings:  true,\n\t\t\topts:                     []Opt{WithErrorOnWarning(), WithSuppressWarnings()},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tclient, err := NewClient(tc.opts...)\n\t\tassert.Check(t, is.Equal(err, tc.expectedError))\n\t\tassert.Check(t, is.Equal(client.errorOnWarning, tc.expectedErrorOnWarnings))\n\t\tassert.Check(t, is.Equal(client.verbose, tc.expectedVerbose))\n\t\tassert.Check(t, is.Equal(client.suppressWarnings, tc.expectedSuppressWarnings))\n\t}\n}\n"
  },
  {
    "path": "client/testdata/docker-compose-profiles.yaml",
    "content": "version: '3'\nservices:\n  backend:\n    image: dummy:tag\n    profiles: ['hello', 'world']\n    ports:\n      - \"80:80\"\n  frontend:\n    image: dummy:tag\n    profiles: [ 'hello' ]\n    ports:\n      - \"80:80\"\n  database:\n    image: dummy:tag\n    profiles: [ 'world' ]\n    ports:\n      - \"80:80\"\n"
  },
  {
    "path": "client/testdata/docker-compose.yaml",
    "content": "version: '3'\nservices:\n  web:\n    image: nginx:latest\n    ports:\n    - \"80:80\"\n\n"
  },
  {
    "path": "client/types.go",
    "content": "package client\n\ntype ConvertBuild string\n\nconst (\n\tLOCAL        ConvertBuild = \"local\"\n\tBUILD_CONFIG ConvertBuild = \"build-config\"\n\tNONE         ConvertBuild = \"none\"\n)\n\ntype KubernetesController string\n\nconst (\n\tDEPLOYMENT             KubernetesController = \"deployment\"\n\tDAEMONSET              KubernetesController = \"daemonSet\"\n\tREPLICATION_CONTROLLER KubernetesController = \"replicationController\"\n)\n\ntype ServiceGroupMode string\n\nconst (\n\tLABEL  ServiceGroupMode = \"label\"\n\tVOLUME ServiceGroupMode = \"volume\"\n)\n\ntype VolumeType string\n\nconst (\n\tPVC       = \"persistentVolumeClaim\"\n\tEMPTYDIR  = \"emptyDir\"\n\tHOSTPATH  = \"hostPath\"\n\tCONFIGMAP = \"configMap\"\n)\n\ntype ConvertOptions struct {\n\tBuild                  *string\n\tPushImage              bool\n\tPushImageRegistry      string\n\tGenerateJson           bool\n\tToStdout               bool\n\tOutFile                string\n\tReplicas               *int\n\tVolumeType             *string\n\tPvcRequestSize         string\n\tWithKomposeAnnotations *bool\n\tInputFiles             []string\n\tProfiles               []string\n\tProvider\n\tGenerateNetworkPolicies bool\n}\n\ntype Provider interface{}\n\ntype Kubernetes struct {\n\tProvider\n\tChart              bool\n\tController         *string\n\tMultiContainerMode bool\n\tServiceGroupMode   *string\n\tServiceGroupName   string\n\tSecretsAsFiles     bool\n}\n\ntype Openshift struct {\n\tProvider\n\tDeploymentConfig   bool\n\tInsecureRepository bool\n\tBuildRepo          string\n\tBuildBranch        string\n}\n"
  },
  {
    "path": "cmd/completion.go",
    "content": "package cmd\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar completion = &cobra.Command{\n\tUse:   \"completion SHELL\",\n\tShort: \"Output shell completion code\",\n\tLong: `Generates shell completion code.\n\nAuto completion supports bash, zsh and fish. Output is to STDOUT.\n\nsource <(kompose completion bash)\nsource <(kompose completion zsh)\nkompose completion fish | source\n\nWill load the shell completion code.\n\t`,\n\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\n\t\terr := Generate(cmd, args)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Error: %s\", err)\n\t\t}\n\n\t\treturn nil\n\t},\n}\n\n// Generate the appropriate autocompletion file\nfunc Generate(cmd *cobra.Command, args []string) error {\n\t// Check the passed in arguments\n\tif len(args) == 0 {\n\t\treturn fmt.Errorf(\"shell not specified. ex. kompose completion [bash|zsh|fish]\")\n\t}\n\tif len(args) > 1 {\n\t\treturn fmt.Errorf(\"too many arguments. Expected only the shell type. ex. kompose completion [bash|zsh|fish]\")\n\t}\n\n\t// Generate bash through cobra if selected\n\tswitch args[0] {\n\tcase \"bash\":\n\t\treturn cmd.Root().GenBashCompletion(os.Stdout)\n\tcase \"zsh\":\n\t\treturn runCompletionZsh(os.Stdout, cmd.Root())\n\tcase \"fish\":\n\t\treturn runCompletionFish(os.Stdout, cmd.Root())\n\tdefault:\n\t\treturn fmt.Errorf(\"not a compatible shell, bash, zsh and fish are only supported\")\n\t}\n}\n\nfunc init() {\n\tRootCmd.AddCommand(completion)\n}\n\n/*\nFish shell auto-completion support\n*/\nfunc runCompletionFish(out io.Writer, kompose *cobra.Command) error {\n\tkompose.GenFishCompletion(out, true)\n\n\tfishInitialization := `\nset -l commands  \"completion convert help version\"\ncomplete -c kompose -f\ncomplete -c kompose -n \"not __fish_seen_subcommand_from $commands\" -a $commands\ncomplete -c kompose -n \"__fish_seen_subcommand_from completion\" -a \"bash zsh fish\"\n`\n\tout.Write([]byte(fishInitialization))\n\treturn nil\n}\n\n/*\nThis is copied from\nhttps://github.com/kubernetes/kubernetes/blob/ea18d5c32ee7c320fe96dda6b0c757476908e696/pkg/kubectl/cmd/completion.go\nin order to generate ZSH completion support.\n*/\nfunc runCompletionZsh(out io.Writer, kompose *cobra.Command) error {\n\tzshInitialization := `\n#compdef kompose\n\n__kompose_bash_source() {\n\talias shopt=':'\n\talias _expand=_bash_expand\n\talias _complete=_bash_comp\n\temulate -L sh\n\tsetopt kshglob noshglob braceexpand\n\tsource \"$@\"\n}\n__kompose_type() {\n\t# -t is not supported by zsh\n\tif [ \"$1\" == \"-t\" ]; then\n\t\tshift\n\t\t# fake Bash 4 to disable \"complete -o nospace\". Instead\n\t\t# \"compopt +-o nospace\" is used in the code to toggle trailing\n\t\t# spaces. We don't support that, but leave trailing spaces on\n\t\t# all the time\n\t\tif [ \"$1\" = \"__kompose_compopt\" ]; then\n\t\t\techo builtin\n\t\t\treturn 0\n\t\tfi\n\tfi\n\ttype \"$@\"\n}\n__kompose_compgen() {\n\tlocal completions w\n\tcompletions=( $(compgen \"$@\") ) || return $?\n\t# filter by given word as prefix\n\twhile [[ \"$1\" = -* && \"$1\" != -- ]]; do\n\t\tshift\n\t\tshift\n\tdone\n\tif [[ \"$1\" == -- ]]; then\n\t\tshift\n\tfi\n\tfor w in \"${completions[@]}\"; do\n\t\tif [[ \"${w}\" = \"$1\"* ]]; then\n\t\t\techo \"${w}\"\n\t\tfi\n\tdone\n}\n__kompose_compopt() {\n\ttrue # don't do anything. Not supported by bashcompinit in zsh\n}\n__kompose_declare() {\n\tif [ \"$1\" == \"-F\" ]; then\n\t\twhence -w \"$@\"\n\telse\n\t\tbuiltin declare \"$@\"\n\tfi\n}\n__kompose_ltrim_colon_completions()\n{\n\tif [[ \"$1\" == *:* && \"$COMP_WORDBREAKS\" == *:* ]]; then\n\t\t# Remove colon-word prefix from COMPREPLY items\n\t\tlocal colon_word=${1%${1##*:}}\n\t\tlocal i=${#COMPREPLY[*]}\n\t\twhile [[ $((--i)) -ge 0 ]]; do\n\t\t\tCOMPREPLY[$i]=${COMPREPLY[$i]#\"$colon_word\"}\n\t\tdone\n\tfi\n}\n__kompose_get_comp_words_by_ref() {\n\tcur=\"${COMP_WORDS[COMP_CWORD]}\"\n\tprev=\"${COMP_WORDS[${COMP_CWORD}-1]}\"\n\twords=(\"${COMP_WORDS[@]}\")\n\tcword=(\"${COMP_CWORD[@]}\")\n}\n__kompose_filedir() {\n\tlocal RET OLD_IFS w qw\n\t__debug \"_filedir $@ cur=$cur\"\n\tif [[ \"$1\" = \\~* ]]; then\n\t\t# somehow does not work. Maybe, zsh does not call this at all\n\t\teval echo \"$1\"\n\t\treturn 0\n\tfi\n\tOLD_IFS=\"$IFS\"\n\tIFS=$'\\n'\n\tif [ \"$1\" = \"-d\" ]; then\n\t\tshift\n\t\tRET=( $(compgen -d) )\n\telse\n\t\tRET=( $(compgen -f) )\n\tfi\n\tIFS=\"$OLD_IFS\"\n\tIFS=\",\" __debug \"RET=${RET[@]} len=${#RET[@]}\"\n\tfor w in ${RET[@]}; do\n\t\tif [[ ! \"${w}\" = \"${cur}\"* ]]; then\n\t\t\tcontinue\n\t\tfi\n\t\tif eval \"[[ \\\"\\${w}\\\" = *.$1 || -d \\\"\\${w}\\\" ]]\"; then\n\t\t\tqw=\"$(__kompose_quote \"${w}\")\"\n\t\t\tif [ -d \"${w}\" ]; then\n\t\t\t\tCOMPREPLY+=(\"${qw}/\")\n\t\t\telse\n\t\t\t\tCOMPREPLY+=(\"${qw}\")\n\t\t\tfi\n\t\tfi\n\tdone\n}\n__kompose_quote() {\n    if [[ $1 == \\'* || $1 == \\\"* ]]; then\n        # Leave out first character\n        printf %q \"${1:1}\"\n    else\n    \tprintf %q \"$1\"\n    fi\n}\nautoload -U +X bashcompinit && bashcompinit\n# use word boundary patterns for BSD or GNU sed\nLWORD='[[:<:]]'\nRWORD='[[:>:]]'\nif sed --help 2>&1 | grep -q GNU; then\n\tLWORD='\\<'\n\tRWORD='\\>'\nfi\n__kompose_convert_bash_to_zsh() {\n\tsed \\\n\t-e 's/declare -F/whence -w/' \\\n\t-e 's/local \\([a-zA-Z0-9_]*\\)=/local \\1; \\1=/' \\\n\t-e 's/flags+=(\"\\(--.*\\)=\")/flags+=(\"\\1\"); two_word_flags+=(\"\\1\")/' \\\n\t-e 's/must_have_one_flag+=(\"\\(--.*\\)=\")/must_have_one_flag+=(\"\\1\")/' \\\n\t-e \"s/${LWORD}_filedir${RWORD}/__kompose_filedir/g\" \\\n\t-e \"s/${LWORD}_get_comp_words_by_ref${RWORD}/__kompose_get_comp_words_by_ref/g\" \\\n\t-e \"s/${LWORD}__ltrim_colon_completions${RWORD}/__kompose_ltrim_colon_completions/g\" \\\n\t-e \"s/${LWORD}compgen${RWORD}/__kompose_compgen/g\" \\\n\t-e \"s/${LWORD}compopt${RWORD}/__kompose_compopt/g\" \\\n\t-e \"s/${LWORD}declare${RWORD}/__kompose_declare/g\" \\\n\t-e \"s/\\\\\\$(type${RWORD}/\\$(__kompose_type/g\" \\\n\t<<'BASH_COMPLETION_EOF'\n`\n\tout.Write([]byte(zshInitialization))\n\n\tbuf := new(bytes.Buffer)\n\tkompose.GenBashCompletion(buf)\n\tout.Write(buf.Bytes())\n\n\tzshTail := `\nBASH_COMPLETION_EOF\n}\n__kompose_bash_source <(__kompose_convert_bash_to_zsh)\n`\n\tout.Write([]byte(zshTail))\n\treturn nil\n}\n"
  },
  {
    "path": "cmd/convert.go",
    "content": "/*\nCopyright 2017 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\nhttp://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*/\n\npackage cmd\n\nimport (\n\t\"strings\"\n\n\t\"github.com/kubernetes/kompose/pkg/app\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/viper\"\n)\n\n// TODO: comment\nvar (\n\tConvertOut                   string\n\tConvertBuildRepo             string\n\tConvertBuildBranch           string\n\tConvertBuild                 string\n\tConvertVolumes               string\n\tConvertPVCRequestSize        string\n\tConvertChart                 bool\n\tConvertDeployment            bool\n\tConvertDaemonSet             bool\n\tConvertReplicationController bool\n\tConvertYaml                  bool\n\tConvertJSON                  bool\n\tConvertStdout                bool\n\tConvertEmptyVols             bool\n\tConvertInsecureRepo          bool\n\tConvertDeploymentConfig      bool\n\tConvertReplicas              int\n\tConvertController            string\n\tConvertProfiles              []string\n\tConvertPushImage             bool\n\tConvertNamespace             string\n\tConvertPushImageRegistry     string\n\tConvertOpt                   kobject.ConvertOptions\n\tConvertYAMLIndent            int\n\tGenerateNetworkPolicies      bool\n\n\tUpBuild string\n\n\tBuildCommand string\n\tPushCommand  string\n\t// WithKomposeAnnotation decides if we will add metadata about this convert to resource's annotation.\n\t// default is true.\n\tWithKomposeAnnotation bool\n\n\t// NoInterpolation decides if we will interpolate environment variables in the compose file.\n\tNoInterpolate bool\n\n\t// MultipleContainerMode which enables creating multi containers in a single pod is a developing function.\n\t// default is false\n\tMultipleContainerMode bool\n\n\tServiceGroupMode string\n\tServiceGroupName string\n\n\t// SecretsAsFiles forces secrets to result in files inside a container instead of symlinked directories containing\n\t// files of the same name. This reproduces the behavior of file-based secrets in docker-compose and should probably\n\t// be the default for kompose, but we must keep compatibility with the previous behavior.\n\t// See https://github.com/kubernetes/kompose/issues/1280 for more details.\n\tSecretsAsFiles bool\n)\n\nvar convertCmd = &cobra.Command{\n\tUse:   \"convert\",\n\tShort: \"Convert a Compose file\",\n\tExample: `  kompose --file compose.yaml convert\n  kompose -f first.yaml -f second.yaml convert\n  kompose --provider openshift --file compose.yaml convert`,\n\tPreRun: func(cmd *cobra.Command, args []string) {\n\n\t\t// Check that build-config wasn't passed in with --provider=kubernetes\n\t\tif GlobalProvider == \"kubernetes\" && UpBuild == \"build-config\" {\n\t\t\tlog.Fatalf(\"build-config is not a valid --build parameter with provider Kubernetes\")\n\t\t}\n\n\t\t// Create the Convert Options.\n\t\tConvertOpt = kobject.ConvertOptions{\n\t\t\tToStdout:                    ConvertStdout,\n\t\t\tCreateChart:                 ConvertChart,\n\t\t\tGenerateYaml:                ConvertYaml,\n\t\t\tGenerateJSON:                ConvertJSON,\n\t\t\tReplicas:                    ConvertReplicas,\n\t\t\tInputFiles:                  GlobalFiles,\n\t\t\tOutFile:                     ConvertOut,\n\t\t\tProvider:                    GlobalProvider,\n\t\t\tCreateD:                     ConvertDeployment,\n\t\t\tCreateDS:                    ConvertDaemonSet,\n\t\t\tCreateRC:                    ConvertReplicationController,\n\t\t\tBuild:                       ConvertBuild,\n\t\t\tBuildRepo:                   ConvertBuildRepo,\n\t\t\tBuildBranch:                 ConvertBuildBranch,\n\t\t\tPushImage:                   ConvertPushImage,\n\t\t\tPushImageRegistry:           ConvertPushImageRegistry,\n\t\t\tCreateDeploymentConfig:      ConvertDeploymentConfig,\n\t\t\tEmptyVols:                   ConvertEmptyVols,\n\t\t\tVolumes:                     ConvertVolumes,\n\t\t\tPVCRequestSize:              ConvertPVCRequestSize,\n\t\t\tInsecureRepository:          ConvertInsecureRepo,\n\t\t\tIsDeploymentFlag:            cmd.Flags().Lookup(\"deployment\").Changed,\n\t\t\tIsDaemonSetFlag:             cmd.Flags().Lookup(\"daemon-set\").Changed,\n\t\t\tIsReplicationControllerFlag: cmd.Flags().Lookup(\"replication-controller\").Changed,\n\t\t\tController:                  strings.ToLower(ConvertController),\n\t\t\tIsReplicaSetFlag:            cmd.Flags().Lookup(\"replicas\").Changed,\n\t\t\tIsDeploymentConfigFlag:      cmd.Flags().Lookup(\"deployment-config\").Changed,\n\t\t\tYAMLIndent:                  ConvertYAMLIndent,\n\t\t\tProfiles:                    ConvertProfiles,\n\t\t\tWithKomposeAnnotation:       WithKomposeAnnotation,\n\t\t\tNoInterpolate:               NoInterpolate,\n\t\t\tMultipleContainerMode:       MultipleContainerMode,\n\t\t\tServiceGroupMode:            ServiceGroupMode,\n\t\t\tServiceGroupName:            ServiceGroupName,\n\t\t\tSecretsAsFiles:              SecretsAsFiles,\n\t\t\tGenerateNetworkPolicies:     GenerateNetworkPolicies,\n\t\t\tBuildCommand:                BuildCommand,\n\t\t\tPushCommand:                 PushCommand,\n\t\t\tNamespace:                   ConvertNamespace,\n\t\t}\n\n\t\tif ServiceGroupMode == \"\" && MultipleContainerMode {\n\t\t\tConvertOpt.ServiceGroupMode = \"label\"\n\t\t}\n\n\t\tapp.ValidateFlags(args, cmd, &ConvertOpt)\n\n\t\t// Since ValidateComposeFiles returns an error, let's validate it and output the error appropriately if the validation fails\n\t\terr := app.ValidateComposeFile(&ConvertOpt)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Error validating compose file: %v\", err)\n\t\t}\n\t},\n\tRun: func(cmd *cobra.Command, args []string) {\n\n\t\tapp.Convert(ConvertOpt)\n\t},\n}\n\nfunc init() {\n\t// Automatically grab environment variables\n\tviper.AutomaticEnv()\n\n\t// Kubernetes only\n\tconvertCmd.Flags().BoolVarP(&ConvertChart, \"chart\", \"c\", false, \"Create a Helm chart for converted objects\")\n\tconvertCmd.Flags().BoolVar(&ConvertDaemonSet, \"daemon-set\", false, \"Generate a Kubernetes daemonset object (deprecated, use --controller instead)\")\n\tconvertCmd.Flags().BoolVarP(&ConvertDeployment, \"deployment\", \"d\", false, \"Generate a Kubernetes deployment object (deprecated, use --controller instead)\")\n\tconvertCmd.Flags().BoolVar(&ConvertReplicationController, \"replication-controller\", false, \"Generate a Kubernetes replication controller object (deprecated, use --controller instead)\")\n\tconvertCmd.Flags().StringVar(&ConvertController, \"controller\", \"\", `Set the output controller (\"deployment\"|\"daemonSet\"|\"replicationController\")`)\n\tconvertCmd.Flags().MarkDeprecated(\"daemon-set\", \"use --controller\")\n\tconvertCmd.Flags().MarkDeprecated(\"deployment\", \"use --controller\")\n\tconvertCmd.Flags().MarkDeprecated(\"replication-controller\", \"use --controller\")\n\tconvertCmd.Flags().MarkHidden(\"chart\")\n\tconvertCmd.Flags().MarkHidden(\"daemon-set\")\n\tconvertCmd.Flags().MarkHidden(\"replication-controller\")\n\tconvertCmd.Flags().MarkHidden(\"deployment\")\n\tconvertCmd.Flags().BoolVar(&MultipleContainerMode, \"multiple-container-mode\", false, \"Create multiple containers grouped by 'kompose.service.group' label\")\n\tconvertCmd.Flags().StringVar(&ServiceGroupMode, \"service-group-mode\", \"\", \"Group multiple service to create single workload by `label`(`kompose.service.group`) or `volume`(shared volumes)\")\n\tconvertCmd.Flags().StringVar(&ServiceGroupName, \"service-group-name\", \"\", \"Using with --service-group-mode=volume to specific a final service name for the group\")\n\tconvertCmd.Flags().MarkDeprecated(\"multiple-container-mode\", \"use --service-group-mode=label\")\n\tconvertCmd.Flags().BoolVar(&SecretsAsFiles, \"secrets-as-files\", false, \"Always convert docker-compose secrets into files instead of symlinked directories\")\n\n\t// OpenShift only\n\tconvertCmd.Flags().BoolVar(&ConvertDeploymentConfig, \"deployment-config\", true, \"Generate an OpenShift deploymentconfig object\")\n\tconvertCmd.Flags().BoolVar(&ConvertInsecureRepo, \"insecure-repository\", false, \"Use an insecure Docker repository for OpenShift ImageStream\")\n\tconvertCmd.Flags().StringVar(&ConvertBuildRepo, \"build-repo\", \"\", \"Specify source repository for buildconfig (default remote origin)\")\n\tconvertCmd.Flags().StringVar(&ConvertBuildBranch, \"build-branch\", \"\", \"Specify repository branch to use for buildconfig (default master)\")\n\tconvertCmd.Flags().MarkDeprecated(\"deployment-config\", \"use --controller\")\n\tconvertCmd.Flags().MarkHidden(\"deployment-config\")\n\tconvertCmd.Flags().MarkHidden(\"insecure-repository\")\n\tconvertCmd.Flags().MarkHidden(\"build-repo\")\n\tconvertCmd.Flags().MarkHidden(\"build-branch\")\n\n\t// Standard between the two\n\tconvertCmd.Flags().StringVar(&ConvertBuild, \"build\", \"none\", `Set the type of build (\"local\"|\"build-config\"(OpenShift only)|\"none\")`)\n\tconvertCmd.Flags().BoolVar(&ConvertPushImage, \"push-image\", false, \"If we should push the docker image we built\")\n\tconvertCmd.Flags().StringVar(&BuildCommand, \"build-command\", \"\", `Set the command used to build the container image, which will override the docker build command. Should be used in conjuction with --push-command flag.`)\n\tconvertCmd.Flags().StringVar(&PushCommand, \"push-command\", \"\", `Set the command used to push the container image. override the docker push command. Should be used in conjuction with --build-command flag.`)\n\tconvertCmd.Flags().StringVar(&ConvertPushImageRegistry, \"push-image-registry\", \"\", \"Specify registry for pushing image, which will override registry from image name\")\n\tconvertCmd.Flags().BoolVarP(&ConvertYaml, \"yaml\", \"y\", false, \"Generate resource files into YAML format\")\n\tconvertCmd.Flags().MarkDeprecated(\"yaml\", \"YAML is the default format now\")\n\tconvertCmd.Flags().MarkShorthandDeprecated(\"y\", \"YAML is the default format now\")\n\tconvertCmd.Flags().BoolVarP(&ConvertJSON, \"json\", \"j\", false, \"Generate resource files into JSON format\")\n\tconvertCmd.Flags().BoolVar(&ConvertStdout, \"stdout\", false, \"Print converted objects to stdout\")\n\tconvertCmd.Flags().StringVarP(&ConvertOut, \"out\", \"o\", \"\", \"Specify a file name or directory to save objects to (if path does not exist, a file will be created)\")\n\tconvertCmd.Flags().IntVar(&ConvertReplicas, \"replicas\", 1, \"Specify the number of replicas in the generated resource spec\")\n\tconvertCmd.Flags().StringVar(&ConvertVolumes, \"volumes\", \"persistentVolumeClaim\", `Volumes to be generated (\"persistentVolumeClaim\"|\"emptyDir\"|\"hostPath\" | \"configMap\")`)\n\tconvertCmd.Flags().StringVar(&ConvertPVCRequestSize, \"pvc-request-size\", \"\", `Specify the size of pvc storage requests in the generated resource spec`)\n\tconvertCmd.Flags().StringVarP(&ConvertNamespace, \"namespace\", \"n\", \"\", `Specify the namespace of the generated resources`)\n\tconvertCmd.Flags().BoolVar(&GenerateNetworkPolicies, \"generate-network-policies\", false, \"Specify whether to generate network policies or not\")\n\n\tconvertCmd.Flags().BoolVar(&WithKomposeAnnotation, \"with-kompose-annotation\", true, \"Add kompose annotations to generated resource\")\n\tconvertCmd.Flags().BoolVar(&NoInterpolate, \"no-interpolate\", false, \"Keep environment variable names in the Compose file\")\n\n\t// Deprecated commands\n\tconvertCmd.Flags().BoolVar(&ConvertEmptyVols, \"emptyvols\", false, \"Use Empty Volumes. Do not generate PVCs\")\n\tconvertCmd.Flags().MarkDeprecated(\"emptyvols\", \"emptyvols has been marked as deprecated. Use --volumes emptyDir\")\n\n\tconvertCmd.Flags().IntVar(&ConvertYAMLIndent, \"indent\", 2, \"Spaces length to indent generated yaml files\")\n\n\tconvertCmd.Flags().StringArrayVar(&ConvertProfiles, \"profile\", []string{}, `Specify the profile to use, can use multiple profiles`)\n\n\t// In order to 'separate' both OpenShift and Kubernetes only flags. A custom help page is created\n\tcustomHelp := `Usage:{{if .Runnable}}\n  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine \"[flags]\"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}\n  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}\n\nAliases:\n  {{.NameAndAliases}}\n{{end}}{{if .HasExample}}\n\nExamples:\n{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}\nAvailable Commands:{{range .Commands}}{{if .IsAvailableCommand}}\n  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}\n\nKubernetes Flags:\n  -c, --chart                    Create a Helm chart for converted objects\n      --controller               Set the output controller (\"deployment\"|\"daemonSet\"|\"replicationController\")\n      --service-group-mode       Group multiple service to create single workload by \"label\"(\"kompose.service.group\") or \"volume\"(shared volumes)\n      --service-group-name       Using with --service-group-mode=volume to specific a final service name for the group\n\nOpenShift Flags:\n      --build-branch             Specify repository branch to use for buildconfig (default is current branch name)\n      --build-repo               Specify source repository for buildconfig (default is current branch's remote url)\n      --insecure-repository      Specify to use insecure docker repository while generating Openshift image stream object\n\nFlags:\n{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}\n\nGlobal Flags:\n{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}\n\nAdditional help topics:{{range .Commands}}{{if .IsHelpCommand}}\n  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}\nUse \"{{.CommandPath}} [command] --help\" for more information about a command.{{end}}\n`\n\t// Set the help template + add the command to root\n\tconvertCmd.SetUsageTemplate(customHelp)\n\n\tRootCmd.AddCommand(convertCmd)\n}\n"
  },
  {
    "path": "cmd/root.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage cmd\n\nimport (\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\t\"github.com/spf13/viper\"\n)\n\n// Logrus hooks\n\n// Hook for error and exit out on warning\ntype errorOnWarningHook struct{}\n\nfunc (errorOnWarningHook) Levels() []log.Level {\n\treturn []log.Level{log.WarnLevel}\n}\n\nfunc (errorOnWarningHook) Fire(entry *log.Entry) error {\n\tlog.Fatalln(entry.Message)\n\treturn nil\n}\n\n// TODO: comment\nvar (\n\tGlobalProvider         string\n\tGlobalVerbose          bool\n\tGlobalSuppressWarnings bool\n\tGlobalErrorOnWarning   bool\n\tGlobalFiles            []string\n)\n\n// RootCmd root level flags and commands\nvar RootCmd = &cobra.Command{\n\tUse:   \"kompose\",\n\tShort: \"A tool helping Compose users move to Kubernetes\",\n\tLong:  `Kompose is a tool to help users who are familiar with docker-compose move to Kubernetes.`,\n\tExample: `  kompose --file compose.yaml convert\n  kompose -f first.yaml -f second.yaml convert\n  kompose --provider openshift --file compose.yaml convert\n  kompose completion bash`,\n\tSilenceErrors: true,\n\t// PersistentPreRun will be \"inherited\" by all children and ran before *every* command unless\n\t// the child has overridden the functionality. This functionality was implemented to check / modify\n\t// all global flag calls regardless of app call.\n\tPersistentPreRun: func(cmd *cobra.Command, args []string) {\n\t\t// Add extra logging when verbosity is passed\n\t\tif GlobalVerbose {\n\t\t\tlog.SetLevel(log.DebugLevel)\n\t\t}\n\n\t\t// Disable the timestamp (Kompose is too fast!)\n\t\tformatter := new(log.TextFormatter)\n\t\tformatter.DisableTimestamp = true\n\t\tformatter.ForceColors = true\n\t\tlog.SetFormatter(formatter)\n\n\t\t// Set the appropriate suppress warnings and error on warning flags\n\t\tif GlobalSuppressWarnings {\n\t\t\tlog.SetLevel(log.ErrorLevel)\n\t\t} else if GlobalErrorOnWarning {\n\t\t\thook := errorOnWarningHook{}\n\t\t\tlog.AddHook(hook)\n\t\t}\n\n\t\t// Error out of the user has not chosen Kubernetes or OpenShift\n\t\tprovider := strings.ToLower(GlobalProvider)\n\t\tif provider != \"kubernetes\" && provider != \"openshift\" {\n\t\t\tlog.Fatalf(\"%s is an unsupported provider. Supported providers are: 'kubernetes', 'openshift'.\", GlobalProvider)\n\t\t}\n\n\t\tv := viper.New()\n\t\tv.BindEnv(\"file\", \"COMPOSE_FILE\")\n\n\t\tcmd.Flags().VisitAll(func(f *pflag.Flag) {\n\t\t\tconfigName := f.Name\n\t\t\tif configName == \"file\" && !f.Changed && v.IsSet(configName) {\n\t\t\t\tGlobalFiles = v.GetStringSlice(configName)\n\t\t\t}\n\t\t})\n\t},\n}\n\n// Execute executes the root level command.\n// It returns an error if any.\nfunc Execute() error {\n\treturn RootCmd.Execute()\n}\n\nfunc init() {\n\tRootCmd.PersistentFlags().BoolVarP(&GlobalVerbose, \"verbose\", \"v\", false, \"verbose output\")\n\tRootCmd.PersistentFlags().BoolVar(&GlobalSuppressWarnings, \"suppress-warnings\", false, \"Suppress all warnings\")\n\tRootCmd.PersistentFlags().BoolVar(&GlobalErrorOnWarning, \"error-on-warning\", false, \"Treat any warning as an error\")\n\tRootCmd.PersistentFlags().StringSliceVarP(&GlobalFiles, \"file\", \"f\", []string{}, \"Specify an alternative compose file\")\n\tRootCmd.PersistentFlags().StringVar(&GlobalProvider, \"provider\", \"kubernetes\", \"Specify a provider. Kubernetes or OpenShift.\")\n}\n"
  },
  {
    "path": "cmd/version.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/kubernetes/kompose/pkg/version\"\n\t\"github.com/spf13/cobra\"\n)\n\n// versionCmd represents the version command\nvar versionCmd = &cobra.Command{\n\tUse:   \"version\",\n\tShort: \"Print the version of Kompose\",\n\tRun: func(cmd *cobra.Command, args []string) {\n\t\t// See pkg/version/version.go for more information as to why we use the git commit / hash value\n\t\tfmt.Println(version.VERSION + \" (\" + version.GITCOMMIT + \")\")\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(versionCmd)\n}\n"
  },
  {
    "path": "code-of-conduct.md",
    "content": "# Kubernetes Community Code of Conduct\n\nPlease refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)\n"
  },
  {
    "path": "docs/404.html",
    "content": "---\npermalink: /404.html\nlayout: default\n---\n\n<style type=\"text/css\" media=\"screen\">\n  .container {\n    margin: 10px auto;\n    max-width: 600px;\n    text-align: center;\n  }\n  h1 {\n    margin: 30px 0;\n    font-size: 4em;\n    line-height: 1;\n    letter-spacing: -1px;\n  }\n</style>\n\n<div class=\"container\">\n  <h1>404</h1>\n\n  <p><strong>Page not found :(</strong></p>\n  <p>The requested page could not be found.</p>\n</div>\n"
  },
  {
    "path": "docs/CNAME",
    "content": "kompose.io"
  },
  {
    "path": "docs/Gemfile",
    "content": "source \"https://rubygems.org\"\n# Hello! This is where you manage which Jekyll version is used to run.\n# When you want to use a different version, change it below, save the\n# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:\n#\n#     bundle exec jekyll serve\n#\n# This will help ensure the proper Jekyll version is running.\n# Happy Jekylling!\ngem \"jekyll\", \"~> 4.0.0\"\n# This is the default theme for new Jekyll sites. You may change this to anything you like.\ngem \"minima\", \"~> 2.5\"\n# If you want to use GitHub Pages, remove the \"gem \"jekyll\"\" above and\n# uncomment the line below. To upgrade, run `bundle update github-pages`.\n# gem \"github-pages\", group: :jekyll_plugins\n# If you have any plugins, put them here!\ngroup :jekyll_plugins do\n  gem \"jekyll-feed\", \"~> 0.12\"\nend\n\n# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem\n# and associated library.\ninstall_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do\n  gem \"tzinfo\", \"~> 1.2\"\n  gem \"tzinfo-data\"\nend\n\n# Performance-booster for watching directories on Windows\ngem \"wdm\", \"~> 0.1.1\", :install_if => Gem.win_platform?\n\ngem \"jekyll-redirect-from\"\n\n"
  },
  {
    "path": "docs/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014-2016 GochoMugo <mugo@forfuture.co.ke>\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software\nwithout restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to\nwhom the Software is furnished to do so, subject to the\nfollowing conditions:\n\nThe above copyright notice and this permission notice shall\nbe included in all copies or substantial portions of the\nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY\nKIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\nOR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "docs/README.md",
    "content": "View the site via:\n\n```sh\nbundle exec jekyll serve .\n```\n\nAnd visiting `localhost:4000` on your browser.\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "title: Kompose\nname: Kompose\nemail: foo@gmail.com\ngithub_page: https://github.com/kubernetes/kompose\nslack_page: https://slack.k8s.io\ndescription: >- # this means to ignore newlines until \"baseurl:\"\n  Convert your Docker Compose file to Kubernetes or OpenShift\nbaseurl: \"\" # the subpath of your site, e.g. /blog\nurl: \"\" # the base hostname & protocol for your site, e.g. http://example.com\nyear: 2024\n\n# Google Analytics number (starts with UA?)\nanalytics: 12345\n\ninstagram: https://www.instagram.com\nfacebook: https://www.facebook.com\n\n# Build settings\ntheme: minima\nplugins:\n  - jekyll-feed\n"
  },
  {
    "path": "docs/_data/dates.yml",
    "content": "- date: \"Saturday May 8\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday May 17\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday May 31\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday June 7\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday June 14\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday June 21\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday July 5\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday July 19\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday July 26\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday August 9\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday August 16\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday August 23\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday August 30\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday September 13\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Friday September 24\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday September 27\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Monday October 4\"\n  green: 20\n  yellow: 20\n  red: 20\n- date: \"Sunday October 10\"\n  green: 20\n  yellow: 20\n  red: 20\n"
  },
  {
    "path": "docs/_data/menu.yml",
    "content": "other_links:\n  \"Installation\": \"/installation/\"\n  \"Getting Started\": \"/getting-started/\"\n  \"User Guide\": \"/user-guide/\"\n  \"Conversion Matrix\": \"/conversion/\"\n  \"Architecture\": \"/architecture/\"\n"
  },
  {
    "path": "docs/_foobar.yml",
    "content": "dates:\n  \"May 8th 2021\"\n"
  },
  {
    "path": "docs/_includes/footer.html",
    "content": "<!-- Footer -->\n<div class=\"footer\">\n  <div class=\"container text-center\">\n    <span class=\"copyright\">\n      We are a Kubernetes incubator graduated project and officially part of the Kubernetes group\n      <br>\n      Apache License 2.0 licensed project\n      <br>\n      © {{ site.year }} Kompose Authors -- All Rights Reserved\n      <br />\n      <a\n        class=\"trademarks\"\n        href=\"https://www.linuxfoundation.org/legal/trademark-usage\"\n        target=\"_blank\"\n        ref=\"noopener\"\n        >Trademarks</a\n      >\n    </span>\n  </div>\n  <div class=\"container\">\n    <div class=\"row text-center\">\n      <div class=\"col-lg-2 col-md-3 col-sm-12\">\n        <div class=\"footer-logo\">\n          <h2>{{ site.name }}</h2>\n        </div>\n      </div>\n      <div class=\"col-lg-6 col-md-6 col-sm-12\">\n        <ul class=\"footer-menu\">\n          <!--\n            {% for item in site.data.menu.footer %}\n            <li><a href=\"{{ item[1] }}\">{{ item[0] }}</a></li>\n            {% endfor %}\n          -->\n\n        </ul>\n      </div>\n      <div class=\"col-lg-4 col-md-3 col-sm-12\">\n        <div class=\"footer-links\">\n          <ul>\n            <li><a href=\"{{ site.slack_page }}\" target=\"_blank\"><img class=\"img-fluid\" src=\"/assets/icons/slack.png\" alt=\"Slack\">Slack</a> </li>\n            <li><a href=\"{{ site.github_page }}\" target=\"_blank\"><img class=\"img-fluid\" src=\"/assets/icons/github.png\" alt=\"GitHub\">GitHub</a> </li>\n          </ul>\n        </div>\n      </div>\n    </div>\n    <!-- Scroll To Top -->\n    <!--<a id=\"back-top\" class=\"back-to-top js-scroll-trigger\" href=\"#main\"></a>-->\n    <!-- Scroll To Top Ends-->\n  </div>\n</div>\n"
  },
  {
    "path": "docs/_includes/meta.html",
    "content": "<!-- Meta -->\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"description\" content=\"{{site.description}}\">\n\n<!-- Cross-site Meta -->\n<meta name=\"robots\" content=\"index, follow\">\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<meta name=\"language\" content=\"English\">\n\n<!-- Metadata loading stuff-->\n<link href=\"/assets/css/bootstrap.min.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" />\n<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:200,300,400,400i,500,600,700%7CMontserrat:300,400,500%7CRoboto\" rel=\"stylesheet\">\n<link rel=\"stylesheet\" href=\"/assets/css/animate.css\"> <!-- Resource style -->\n<link rel=\"stylesheet\" href=\"/assets/css/owl.carousel.css\">\n<link rel=\"stylesheet\" href=\"/assets/css/owl.theme.css\">\n<link rel=\"stylesheet\" href=\"/assets/css/magnific-popup.css\">\n<link rel=\"stylesheet\" href=\"/assets/css/ionicons.min.css\"> <!-- Resource style -->\n<link rel=\"stylesheet\" href=\"/assets/css/style.css\">\n<link rel=\"stylesheet\" href=\"/assets/css/github-markdown.css\">\n\n\n<!-- Favicons -->\n<!-- Generate using: https://realfavicongenerator.net/ and put information in /assets/favicons/ folder -->\n<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/assets/favicons/apple-touch-icon.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/assets/favicons/favicon-32x32.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/assets/favicons/favicon-16x16.png\">\n<link rel=\"manifest\" href=\"/assets/favicons/site.webmanifest\">\n<link rel=\"mask-icon\" href=\"/assets/favicons/safari-pinned-tab.svg\" color=\"#5bbad5\">\n<link rel=\"shortcut icon\" href=\"/assets/favicons/favicon.ico\">\n<meta name=\"msapplication-TileColor\" content=\"#da532c\">\n<meta name=\"msapplication-config\" content=\"/assets/favicons/browserconfig.xml\">\n<meta name=\"theme-color\" content=\"#ffffff\">\n\n<!-- ANALYTICS -->\n<!-- Global site tag (gtag.js) - Google Analytics -->\n<script async src=\"https://www.googletagmanager.com/gtag/js?id={{ site.analytics }}\"></script>\n<script>\n  window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\n\ngtag('config', '{{ site.analytics }}');\n</script>\n\n"
  },
  {
    "path": "docs/_includes/navbar.html",
    "content": "      <!-- Navbar Section -->\n      <nav class=\"navbar navbar-expand-md navbar-light bg-light fixed-top\">\n        <div class=\"container\">\n          <a class=\"navbar-brand\" href=\"/\">\n            <img class=\"navbar-logo\" src=\"/assets/images/logo.png\" alt=\"logo\"/>\n          </a>\n          <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\n            <span class=\"navbar-toggler-icon\"></span>\n          </button>\n          <div class=\"collapse navbar-collapse\" id=\"navbarSupportedContent\">\n            <ul class=\"navbar-nav ml-auto navbar-right\">\n              {% for item in site.data.menu.other_links %}\n                <li class=\"nav-item\"><a class=\"nav-link\" href=\"{{ item[1] }}\">{{ item[0] }}</a></li>\n              {% endfor %}\n            </ul>\n          </div>\n        </div>\n      </nav><!-- Navbar End -->\n"
  },
  {
    "path": "docs/_layouts/default.html",
    "content": "<!DOCTYPE html>\r\n<whtml lang=\"en\">\r\n  <head>\r\n\r\n    <!-- Metadata -->\r\n    <meta charset=\"utf-8\">\r\n    <title>{{ site.title }} - {{ page.title }}</title>\r\n    <meta name=\"title\" content=\"{{ site.title }} - {{ page.title }}\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n\r\n    {% include meta.html %}\r\n\r\n  </head>\r\n  <body>\r\n    <div class=\"wrapper\">\r\n\r\n      {% include navbar.html %}\r\n\r\n      <div id=\"main\" class=\"main\">\r\n        <div class=\"first\"><!-- Hero Section-->\r\n          <div class=\"container\">\r\n            <div class=\"row\">\r\n                  <div class=\"markdown-body\">\r\n                    {{ content }}\r\n                  </div>\r\n            </div>\r\n\r\n            <div class=\"questions flex-out align-center wow fadeIn\">\r\n              <p>\r\n              </p>\r\n            </div>\r\n          </div>\r\n\r\n        </div><!-- Hero End -->\r\n      </div>\r\n\r\n\r\n      {% include footer.html %}\r\n\r\n    </div> <!-- Main -->\r\n\r\n\r\n    <!-- Jquery and Js Plugins -->\r\n    <script src=\"/assets/js/jquery-2.1.1.js\"></script>\r\n    <script src=\"/assets/js/popper.min.js\"></script>\r\n    <script src=\"/assets/js/jquery.validate.min.js\"></script>\r\n    <script src=\"/assets/js/bootstrap.min.js\"></script>\r\n    <script src=\"/assets/js/plugins.js\"></script>\r\n    <script src=\"/assets/js/menu.js\"></script>\r\n    <script src=\"/assets/js/custom.js\"></script>\r\n    <script>\r\n      $('.navbar-nav>li>a').on('click', function(){\r\n\r\n        $('.navbar-collapse').collapse('hide');\r\n\r\n      });\r\n    </script>\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "docs/_layouts/index.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n  <head>\r\n\r\n    <!-- Metadata -->\r\n    <meta charset=\"utf-8\">\r\n    <title>{{ site.title }} - {{ site.description }}</title>\r\n    <meta name=\"title\" content=\"{{ site.title }} - {{ site.description }}\">\r\n\r\n    {% include meta.html %}\r\n\r\n  </head>\r\n  <body>\r\n    <div class=\"wrapper\">\r\n\r\n      {% include navbar.html %}\r\n\r\n      <div id=\"main\" class=\"main\">\r\n        <div class=\"first home-3\"><!-- Hero Section-->\r\n            <div class=\"questions flex-out align-center wow fadeIn\">\r\n              <p>\r\n              An official Kubernetes project, located at <a href=\"https://github.com/kubernetes/kompose\" target=\"_blank\">github.com/kubernetes/kompose</a>\r\n              </p>\r\n            </div>\r\n          <div class=\"container\">\r\n            <div class=\"row\">\r\n              <div class=\"col-md-5\">\r\n                <div class=\"hero-content wow fadeIn\">\r\n                  <div class=\"hero-content-inner\">\r\n                    <h4>Go from Docker Compose to Kubernetes</h4>\r\n                    <h1>Kompose</h1>\r\n                    <p>\r\n                    Kompose is a conversion tool for Docker Compose to container orchestrators such as Kubernetes (or OpenShift).\r\n\r\n                    </p>\r\n                    <a class=\"btn-action\" href=\"/installation\">Installation</a>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n              <div class=\"col-md-7 markdown-body code-example\">\r\n                  {{ content }}\r\n              </div>\r\n            </div>\r\n\r\n          </div>\r\n\r\n        </div><!-- Hero End -->\r\n\r\n        <div id=\"what\" class=\"what home-3\"><!-- Hero Section-->\r\n          <div class=\"container\">\r\n            <div class=\"flex-intro align-center wow fadeIn\">\r\n              <h2>Get started on Kubernetes immediately</h2>\r\n              <p>\r\n              So easy your human companion could do it too!\r\n              </p>\r\n            </div>\r\n            <div class=\"row\">\r\n\r\n              <div class=\"col-md-7\">\r\n                <div class=\"hero-img loop-video\">\r\n                  <video class=\"embed-responsive drone-video\" autoplay loop muted>\r\n                    <source src=\"assets/video/cat.webm\" type=\"video/webm\" />\r\n                  </video>\r\n                </div>\r\n              </div>\r\n\r\n              <div class=\"col-md-5\">\r\n                <div class=\"hero-content wow fadeIn\">\r\n                  <div class=\"hero-content-inner\">\r\n                    <p>\r\n                    Why do cats (and developers) like Kompose?\r\n                    <br>\r\n                    <br>\r\n                    Developers love to simplify their development environment with Docker Compose.\r\n                    <br>\r\n                    <br>\r\n                    With Kompose, you can now push the same file to a production container orchestrator!\r\n                    </p>\r\n                    <a class=\"btn-action\" href=\"/getting-started\">Getting Started</a>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n\r\n\r\n            </div>\r\n\r\n          </div>\r\n        </div><!-- Hero End -->\r\n\r\n        <div id=\"date\" class=\"home home-3\"><!-- Hero Section-->\r\n          <div class=\"container\">\r\n            <div class=\"flex-intro align-center wow fadeIn\">\r\n              <h2>Built for container engineers</h2>\r\n              <p>\r\n              Our conversions are not always 1-1 from Docker Compose to Kubernetes, but we will help get you 99% of the way there!\r\n              </p>\r\n            </div>\r\n            <div class=\"row\">\r\n\r\n              <div class=\"col-md-5\">\r\n                <div class=\"hero-content wow fadeIn\">\r\n                  <div class=\"hero-content-inner\">\r\n                    <h4>The awesome features</h4>\r\n                    <p>\r\n                    • Compatibility with multiple versions of Docker Compose\r\n                    <br>\r\n                    • A <a href=\"/conversion\">conversion matrix</a> that outlines all compatible values and versions\r\n                    <br>\r\n                    • An in-depth <a href=\"/user-guide\">user guide</a> to use advanced features such as LoadBalancer, Service and TLS\r\n                    <br>\r\n                    • <a href=\"/user-guide#labels\">Labels</a> that provide the extra 1% needed to get to 1-1 conversion\r\n                    </p>\r\n                    <a class=\"btn-action\" href=\"/user-guide\">User Guide</a>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n\r\n              <div class=\"col-md-7\">\r\n                <div class=\"hero-img loop-video\">\r\n                  <video class=\"embed-responsive drone-video\" autoplay loop muted>\r\n                    <source src=\"assets/video/coding.webm\" type=\"video/webm\" />\r\n                  </video>\r\n                </div>\r\n              </div>\r\n\r\n            </div>\r\n\r\n          </div>\r\n        </div><!-- Hero End -->\r\n\r\n      </div>\r\n\r\n\r\n      {% include footer.html %}\r\n\r\n    </div> <!-- Main -->\r\n\r\n\r\n    <!-- Jquery and Js Plugins -->\r\n    <script src=\"assets/js/jquery-2.1.1.js\"></script>\r\n    <script src=\"assets/js/popper.min.js\"></script>\r\n    <script src=\"assets/js/jquery.validate.min.js\"></script>\r\n    <script src=\"assets/js/bootstrap.min.js\"></script>\r\n    <script src=\"assets/js/plugins.js\"></script>\r\n    <script src=\"assets/js/menu.js\"></script>\r\n    <script src=\"assets/js/custom.js\"></script>\r\n    <script>\r\n      $('.navbar-nav>li>a').on('click', function(){\r\n\r\n        $('.navbar-collapse').collapse('hide');\r\n\r\n      });\r\n    </script>\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "docs/architecture.md",
    "content": "---\nlayout: default\npermalink: /architecture/\ntitle: Architecture\nredirect_from:\n  - /docs/architecture.md/\n  - /docs/architecture/\n---\n\n# Architecture and Internal Design\n\n* TOC\n{:toc}\n\n`kompose` has 3 stages: _Loader_, _Transformer_ and _Outputter_. Each stage should have a well-defined interface, so it is easy to write a new Loader, Transformer, or Outputters and plug it in. Currently, only Loader and Transformer interfaces are defined.\n\n![Design Diagram](https://raw.githubusercontent.com/kubernetes/kompose/main/docs/images/design_diagram.png)\n\n## Loader\n\nThe Loader reads the input file now `kompose` supports [Compose](https://docs.docker.com/compose) v1, v2 and converts it to KomposeObject.\n\nLoader is represented by a Loader interface:\n\n```go\ntype Loader interface {\n      LoadFile(file string) kobject.KomposeObject\n}\n```\n\nEvery loader “implementation” should be placed into `kompose/pkg/loader` (like compose). More input formats will be supported in the future. You can take a look for more details at:\n\n- [kompose/pkg/loader](https://github.com/kubernetes/kompose/tree/master/pkg/loader)\n- [kompose/pkg/loader/compose](https://github.com/kubernetes/kompose/tree/master/pkg/loader/compose)\n\n## KomposeObject\n\n`KomposeObject` is Kompose internal representation of all containers loaded from input file. First version of `KomposeObject` looks like this (source: [kobject.go](https://github.com/kubernetes/kompose/blob/master/pkg/kobject/kobject.go)):\n\n```go\n// KomposeObject holds the generic struct of Kompose transformation\ntype KomposeObject struct {\n    ServiceConfigs map[string]ServiceConfig\n}\n\n// ServiceConfig holds the basic struct of a container\ntype ServiceConfig struct {\n    ContainerName string\n    Image         string\n    Environment   []EnvVar\n    Port          []Ports\n    Command       []string\n    WorkingDir    string\n    Args          []string\n    Volumes       []string\n    Network       []string\n    Labels        map[string]string\n    Annotations   map[string]string\n    CPUSet        string\n    CPUShares     int64\n    CPUQuota      int64\n    CapAdd        []string\n    CapDrop       []string\n    Entrypoint    []string\n    Expose        []string\n    Privileged    bool\n    Restart       string\n    User          string\n}\n```\n\n## Transformer\n\nThe Transformer takes KomposeObject and converts it to target/output format (currently, there are sets of Kubernetes/OpenShift objects). Similar to the `Loader`, Transformer is represented by a Transformer interface:\n\n```go\ntype Transformer interface {\n     Transform(kobject.KomposeObject, kobject.ConvertOptions) []runtime.Object\n}\n```\n\nIf you wish to add more providers containing different kinds of objects, the Transformer would be the place to look into. Currently, Kompose supports Kubernetes (by default) and OpenShift providers. More details at:\n\n- [kompose/pkg/transformer](https://github.com/kubernetes/kompose/tree/master/pkg/transformer)\n- [kompose/pkg/transformer/Kubernetes](https://github.com/kubernetes/kompose/tree/master/pkg/transformer/kubernetes)\n- [kompose/pkg/transformer/openshift](https://github.com/kubernetes/kompose/tree/master/pkg/transformer/openshift)\n\n## Outputter\n\nThe Outputter takes the Transformer result and executes the given action. For example, action can display results to stdout or directly deploy artifacts to Kubernetes/OpenShift.\n"
  },
  {
    "path": "docs/assets/css/animate.css",
    "content": "\r\n/*!\r\nAnimate.css - http://daneden.me/animate\r\nLicensed under the MIT license\r\n\r\nCopyright (c) 2013 Daniel Eden\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n*/\r\n\r\n.animated {\r\n  -webkit-animation-duration: 1s;\r\n  animation-duration: 1s;\r\n  -webkit-animation-fill-mode: both;\r\n  animation-fill-mode: both;\r\n}\r\n\r\n.animated.hinge {\r\n  -webkit-animation-duration: 2s;\r\n  animation-duration: 2s;\r\n}\r\n\r\n@-webkit-keyframes bounce {\r\n  0%, 20%, 50%, 80%, 100% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: translateY(-30px);\r\n    transform: translateY(-30px);\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: translateY(-15px);\r\n    transform: translateY(-15px);\r\n  }\r\n}\r\n\r\n@keyframes bounce {\r\n  0%, 20%, 50%, 80%, 100% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: translateY(-30px);\r\n    -ms-transform: translateY(-30px);\r\n    transform: translateY(-30px);\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: translateY(-15px);\r\n    -ms-transform: translateY(-15px);\r\n    transform: translateY(-15px);\r\n  }\r\n}\r\n\r\n.bounce {\r\n  -webkit-animation-name: bounce;\r\n  animation-name: bounce;\r\n}\r\n\r\n@-webkit-keyframes flash {\r\n  0%, 50%, 100% {\r\n    opacity: 1;\r\n  }\r\n\r\n  25%, 75% {\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes flash {\r\n  0%, 50%, 100% {\r\n    opacity: 1;\r\n  }\r\n\r\n  25%, 75% {\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.flash {\r\n  -webkit-animation-name: flash;\r\n  animation-name: flash;\r\n}\r\n\r\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\r\n\r\n@-webkit-keyframes pulse {\r\n  0% {\r\n    -webkit-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n\r\n  50% {\r\n    -webkit-transform: scale(1.1);\r\n    transform: scale(1.1);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n}\r\n\r\n@keyframes pulse {\r\n  0% {\r\n    -webkit-transform: scale(1);\r\n    -ms-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n\r\n  50% {\r\n    -webkit-transform: scale(1.1);\r\n    -ms-transform: scale(1.1);\r\n    transform: scale(1.1);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: scale(1);\r\n    -ms-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n}\r\n\r\n.pulse {\r\n  -webkit-animation-name: pulse;\r\n  animation-name: pulse;\r\n}\r\n\r\n@-webkit-keyframes shake {\r\n  0%, 100% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  10%, 30%, 50%, 70%, 90% {\r\n    -webkit-transform: translateX(-10px);\r\n    transform: translateX(-10px);\r\n  }\r\n\r\n  20%, 40%, 60%, 80% {\r\n    -webkit-transform: translateX(10px);\r\n    transform: translateX(10px);\r\n  }\r\n}\r\n\r\n@keyframes shake {\r\n  0%, 100% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  10%, 30%, 50%, 70%, 90% {\r\n    -webkit-transform: translateX(-10px);\r\n    -ms-transform: translateX(-10px);\r\n    transform: translateX(-10px);\r\n  }\r\n\r\n  20%, 40%, 60%, 80% {\r\n    -webkit-transform: translateX(10px);\r\n    -ms-transform: translateX(10px);\r\n    transform: translateX(10px);\r\n  }\r\n}\r\n\r\n.shake {\r\n  -webkit-animation-name: shake;\r\n  animation-name: shake;\r\n}\r\n\r\n@-webkit-keyframes swing {\r\n  20% {\r\n    -webkit-transform: rotate(15deg);\r\n    transform: rotate(15deg);\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: rotate(-10deg);\r\n    transform: rotate(-10deg);\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: rotate(5deg);\r\n    transform: rotate(5deg);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: rotate(-5deg);\r\n    transform: rotate(-5deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: rotate(0deg);\r\n    transform: rotate(0deg);\r\n  }\r\n}\r\n\r\n@keyframes swing {\r\n  20% {\r\n    -webkit-transform: rotate(15deg);\r\n    -ms-transform: rotate(15deg);\r\n    transform: rotate(15deg);\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: rotate(-10deg);\r\n    -ms-transform: rotate(-10deg);\r\n    transform: rotate(-10deg);\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: rotate(5deg);\r\n    -ms-transform: rotate(5deg);\r\n    transform: rotate(5deg);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: rotate(-5deg);\r\n    -ms-transform: rotate(-5deg);\r\n    transform: rotate(-5deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: rotate(0deg);\r\n    -ms-transform: rotate(0deg);\r\n    transform: rotate(0deg);\r\n  }\r\n}\r\n\r\n.swing {\r\n  -webkit-transform-origin: top center;\r\n  -ms-transform-origin: top center;\r\n  transform-origin: top center;\r\n  -webkit-animation-name: swing;\r\n  animation-name: swing;\r\n}\r\n\r\n@-webkit-keyframes tada {\r\n  0% {\r\n    -webkit-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n\r\n  10%, 20% {\r\n    -webkit-transform: scale(0.9) rotate(-3deg);\r\n    transform: scale(0.9) rotate(-3deg);\r\n  }\r\n\r\n  30%, 50%, 70%, 90% {\r\n    -webkit-transform: scale(1.1) rotate(3deg);\r\n    transform: scale(1.1) rotate(3deg);\r\n  }\r\n\r\n  40%, 60%, 80% {\r\n    -webkit-transform: scale(1.1) rotate(-3deg);\r\n    transform: scale(1.1) rotate(-3deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: scale(1) rotate(0);\r\n    transform: scale(1) rotate(0);\r\n  }\r\n}\r\n\r\n@keyframes tada {\r\n  0% {\r\n    -webkit-transform: scale(1);\r\n    -ms-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n\r\n  10%, 20% {\r\n    -webkit-transform: scale(0.9) rotate(-3deg);\r\n    -ms-transform: scale(0.9) rotate(-3deg);\r\n    transform: scale(0.9) rotate(-3deg);\r\n  }\r\n\r\n  30%, 50%, 70%, 90% {\r\n    -webkit-transform: scale(1.1) rotate(3deg);\r\n    -ms-transform: scale(1.1) rotate(3deg);\r\n    transform: scale(1.1) rotate(3deg);\r\n  }\r\n\r\n  40%, 60%, 80% {\r\n    -webkit-transform: scale(1.1) rotate(-3deg);\r\n    -ms-transform: scale(1.1) rotate(-3deg);\r\n    transform: scale(1.1) rotate(-3deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: scale(1) rotate(0);\r\n    -ms-transform: scale(1) rotate(0);\r\n    transform: scale(1) rotate(0);\r\n  }\r\n}\r\n\r\n.tada {\r\n  -webkit-animation-name: tada;\r\n  animation-name: tada;\r\n}\r\n\r\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\r\n\r\n@-webkit-keyframes wobble {\r\n  0% {\r\n    -webkit-transform: translateX(0%);\r\n    transform: translateX(0%);\r\n  }\r\n\r\n  15% {\r\n    -webkit-transform: translateX(-25%) rotate(-5deg);\r\n    transform: translateX(-25%) rotate(-5deg);\r\n  }\r\n\r\n  30% {\r\n    -webkit-transform: translateX(20%) rotate(3deg);\r\n    transform: translateX(20%) rotate(3deg);\r\n  }\r\n\r\n  45% {\r\n    -webkit-transform: translateX(-15%) rotate(-3deg);\r\n    transform: translateX(-15%) rotate(-3deg);\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: translateX(10%) rotate(2deg);\r\n    transform: translateX(10%) rotate(2deg);\r\n  }\r\n\r\n  75% {\r\n    -webkit-transform: translateX(-5%) rotate(-1deg);\r\n    transform: translateX(-5%) rotate(-1deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0%);\r\n    transform: translateX(0%);\r\n  }\r\n}\r\n\r\n@keyframes wobble {\r\n  0% {\r\n    -webkit-transform: translateX(0%);\r\n    -ms-transform: translateX(0%);\r\n    transform: translateX(0%);\r\n  }\r\n\r\n  15% {\r\n    -webkit-transform: translateX(-25%) rotate(-5deg);\r\n    -ms-transform: translateX(-25%) rotate(-5deg);\r\n    transform: translateX(-25%) rotate(-5deg);\r\n  }\r\n\r\n  30% {\r\n    -webkit-transform: translateX(20%) rotate(3deg);\r\n    -ms-transform: translateX(20%) rotate(3deg);\r\n    transform: translateX(20%) rotate(3deg);\r\n  }\r\n\r\n  45% {\r\n    -webkit-transform: translateX(-15%) rotate(-3deg);\r\n    -ms-transform: translateX(-15%) rotate(-3deg);\r\n    transform: translateX(-15%) rotate(-3deg);\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: translateX(10%) rotate(2deg);\r\n    -ms-transform: translateX(10%) rotate(2deg);\r\n    transform: translateX(10%) rotate(2deg);\r\n  }\r\n\r\n  75% {\r\n    -webkit-transform: translateX(-5%) rotate(-1deg);\r\n    -ms-transform: translateX(-5%) rotate(-1deg);\r\n    transform: translateX(-5%) rotate(-1deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0%);\r\n    -ms-transform: translateX(0%);\r\n    transform: translateX(0%);\r\n  }\r\n}\r\n\r\n.wobble {\r\n  -webkit-animation-name: wobble;\r\n  animation-name: wobble;\r\n}\r\n\r\n@-webkit-keyframes bounceIn {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: scale(.3);\r\n    transform: scale(.3);\r\n  }\r\n\r\n  50% {\r\n    opacity: 1;\r\n    -webkit-transform: scale(1.05);\r\n    transform: scale(1.05);\r\n  }\r\n\r\n  70% {\r\n    -webkit-transform: scale(.9);\r\n    transform: scale(.9);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n}\r\n\r\n@keyframes bounceIn {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: scale(.3);\r\n    -ms-transform: scale(.3);\r\n    transform: scale(.3);\r\n  }\r\n\r\n  50% {\r\n    opacity: 1;\r\n    -webkit-transform: scale(1.05);\r\n    -ms-transform: scale(1.05);\r\n    transform: scale(1.05);\r\n  }\r\n\r\n  70% {\r\n    -webkit-transform: scale(.9);\r\n    -ms-transform: scale(.9);\r\n    transform: scale(.9);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: scale(1);\r\n    -ms-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n}\r\n\r\n.bounceIn {\r\n  -webkit-animation-name: bounceIn;\r\n  animation-name: bounceIn;\r\n}\r\n\r\n@-webkit-keyframes bounceInDown {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(30px);\r\n    transform: translateY(30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateY(-10px);\r\n    transform: translateY(-10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes bounceInDown {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    -ms-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(30px);\r\n    -ms-transform: translateY(30px);\r\n    transform: translateY(30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateY(-10px);\r\n    -ms-transform: translateY(-10px);\r\n    transform: translateY(-10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.bounceInDown {\r\n  -webkit-animation-name: bounceInDown;\r\n  animation-name: bounceInDown;\r\n}\r\n\r\n@-webkit-keyframes bounceInLeft {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(30px);\r\n    transform: translateX(30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateX(-10px);\r\n    transform: translateX(-10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes bounceInLeft {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    -ms-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(30px);\r\n    -ms-transform: translateX(30px);\r\n    transform: translateX(30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateX(-10px);\r\n    -ms-transform: translateX(-10px);\r\n    transform: translateX(-10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.bounceInLeft {\r\n  -webkit-animation-name: bounceInLeft;\r\n  animation-name: bounceInLeft;\r\n}\r\n\r\n@-webkit-keyframes bounceInRight {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(-30px);\r\n    transform: translateX(-30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateX(10px);\r\n    transform: translateX(10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes bounceInRight {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    -ms-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(-30px);\r\n    -ms-transform: translateX(-30px);\r\n    transform: translateX(-30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateX(10px);\r\n    -ms-transform: translateX(10px);\r\n    transform: translateX(10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.bounceInRight {\r\n  -webkit-animation-name: bounceInRight;\r\n  animation-name: bounceInRight;\r\n}\r\n\r\n@-webkit-keyframes bounceInUp {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(-30px);\r\n    transform: translateY(-30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateY(10px);\r\n    transform: translateY(10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes bounceInUp {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    -ms-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n\r\n  60% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(-30px);\r\n    -ms-transform: translateY(-30px);\r\n    transform: translateY(-30px);\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateY(10px);\r\n    -ms-transform: translateY(10px);\r\n    transform: translateY(10px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.bounceInUp {\r\n  -webkit-animation-name: bounceInUp;\r\n  animation-name: bounceInUp;\r\n}\r\n\r\n@-webkit-keyframes bounceOut {\r\n  0% {\r\n    -webkit-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n\r\n  25% {\r\n    -webkit-transform: scale(.95);\r\n    transform: scale(.95);\r\n  }\r\n\r\n  50% {\r\n    opacity: 1;\r\n    -webkit-transform: scale(1.1);\r\n    transform: scale(1.1);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: scale(.3);\r\n    transform: scale(.3);\r\n  }\r\n}\r\n\r\n@keyframes bounceOut {\r\n  0% {\r\n    -webkit-transform: scale(1);\r\n    -ms-transform: scale(1);\r\n    transform: scale(1);\r\n  }\r\n\r\n  25% {\r\n    -webkit-transform: scale(.95);\r\n    -ms-transform: scale(.95);\r\n    transform: scale(.95);\r\n  }\r\n\r\n  50% {\r\n    opacity: 1;\r\n    -webkit-transform: scale(1.1);\r\n    -ms-transform: scale(1.1);\r\n    transform: scale(1.1);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: scale(.3);\r\n    -ms-transform: scale(.3);\r\n    transform: scale(.3);\r\n  }\r\n}\r\n\r\n.bounceOut {\r\n  -webkit-animation-name: bounceOut;\r\n  animation-name: bounceOut;\r\n}\r\n\r\n@-webkit-keyframes bounceOutDown {\r\n  0% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(-20px);\r\n    transform: translateY(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n}\r\n\r\n@keyframes bounceOutDown {\r\n  0% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(-20px);\r\n    -ms-transform: translateY(-20px);\r\n    transform: translateY(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    -ms-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n}\r\n\r\n.bounceOutDown {\r\n  -webkit-animation-name: bounceOutDown;\r\n  animation-name: bounceOutDown;\r\n}\r\n\r\n@-webkit-keyframes bounceOutLeft {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(20px);\r\n    transform: translateX(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n}\r\n\r\n@keyframes bounceOutLeft {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(20px);\r\n    -ms-transform: translateX(20px);\r\n    transform: translateX(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    -ms-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n}\r\n\r\n.bounceOutLeft {\r\n  -webkit-animation-name: bounceOutLeft;\r\n  animation-name: bounceOutLeft;\r\n}\r\n\r\n@-webkit-keyframes bounceOutRight {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(-20px);\r\n    transform: translateX(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n}\r\n\r\n@keyframes bounceOutRight {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(-20px);\r\n    -ms-transform: translateX(-20px);\r\n    transform: translateX(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    -ms-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n}\r\n\r\n.bounceOutRight {\r\n  -webkit-animation-name: bounceOutRight;\r\n  animation-name: bounceOutRight;\r\n}\r\n\r\n@-webkit-keyframes bounceOutUp {\r\n  0% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(20px);\r\n    transform: translateY(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n}\r\n\r\n@keyframes bounceOutUp {\r\n  0% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  20% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(20px);\r\n    -ms-transform: translateY(20px);\r\n    transform: translateY(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    -ms-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n}\r\n\r\n.bounceOutUp {\r\n  -webkit-animation-name: bounceOutUp;\r\n  animation-name: bounceOutUp;\r\n}\r\n\r\n@-webkit-keyframes fadeIn {\r\n  0% {\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes fadeIn {\r\n  0% {\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.fadeIn {\r\n  -webkit-animation-name: fadeIn;\r\n  animation-name: fadeIn;\r\n}\r\n\r\n@-webkit-keyframes fadeInDown {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-20px);\r\n    transform: translateY(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInDown {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-20px);\r\n    -ms-transform: translateY(-20px);\r\n    transform: translateY(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.fadeInDown {\r\n  -webkit-animation-name: fadeInDown;\r\n  animation-name: fadeInDown;\r\n}\r\n\r\n@-webkit-keyframes fadeInDownBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInDownBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    -ms-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.fadeInDownBig {\r\n  -webkit-animation-name: fadeInDownBig;\r\n  animation-name: fadeInDownBig;\r\n}\r\n\r\n@-webkit-keyframes fadeInLeft {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-20px);\r\n    transform: translateX(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInLeft {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-20px);\r\n    -ms-transform: translateX(-20px);\r\n    transform: translateX(-20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.fadeInLeft {\r\n  -webkit-animation-name: fadeInLeft;\r\n  animation-name: fadeInLeft;\r\n}\r\n\r\n@-webkit-keyframes fadeInLeftBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInLeftBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    -ms-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.fadeInLeftBig {\r\n  -webkit-animation-name: fadeInLeftBig;\r\n  animation-name: fadeInLeftBig;\r\n}\r\n\r\n@-webkit-keyframes fadeInRight {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(20px);\r\n    transform: translateX(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInRight {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(20px);\r\n    -ms-transform: translateX(20px);\r\n    transform: translateX(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.fadeInRight {\r\n  -webkit-animation-name: fadeInRight;\r\n  animation-name: fadeInRight;\r\n}\r\n\r\n@-webkit-keyframes fadeInRightBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInRightBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    -ms-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.fadeInRightBig {\r\n  -webkit-animation-name: fadeInRightBig;\r\n  animation-name: fadeInRightBig;\r\n}\r\n\r\n@-webkit-keyframes fadeInUp {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(20px);\r\n    transform: translateY(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInUp {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(20px);\r\n    -ms-transform: translateY(20px);\r\n    transform: translateY(20px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.fadeInUp {\r\n  -webkit-animation-name: fadeInUp;\r\n  animation-name: fadeInUp;\r\n}\r\n\r\n@-webkit-keyframes fadeInUpBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes fadeInUpBig {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    -ms-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.fadeInUpBig {\r\n  -webkit-animation-name: fadeInUpBig;\r\n  animation-name: fadeInUpBig;\r\n}\r\n\r\n@-webkit-keyframes fadeOut {\r\n  0% {\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes fadeOut {\r\n  0% {\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.fadeOut {\r\n  -webkit-animation-name: fadeOut;\r\n  animation-name: fadeOut;\r\n}\r\n\r\n@-webkit-keyframes fadeOutDown {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(20px);\r\n    transform: translateY(20px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutDown {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(20px);\r\n    -ms-transform: translateY(20px);\r\n    transform: translateY(20px);\r\n  }\r\n}\r\n\r\n.fadeOutDown {\r\n  -webkit-animation-name: fadeOutDown;\r\n  animation-name: fadeOutDown;\r\n}\r\n\r\n@-webkit-keyframes fadeOutDownBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutDownBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(2000px);\r\n    -ms-transform: translateY(2000px);\r\n    transform: translateY(2000px);\r\n  }\r\n}\r\n\r\n.fadeOutDownBig {\r\n  -webkit-animation-name: fadeOutDownBig;\r\n  animation-name: fadeOutDownBig;\r\n}\r\n\r\n@-webkit-keyframes fadeOutLeft {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-20px);\r\n    transform: translateX(-20px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutLeft {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-20px);\r\n    -ms-transform: translateX(-20px);\r\n    transform: translateX(-20px);\r\n  }\r\n}\r\n\r\n.fadeOutLeft {\r\n  -webkit-animation-name: fadeOutLeft;\r\n  animation-name: fadeOutLeft;\r\n}\r\n\r\n@-webkit-keyframes fadeOutLeftBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutLeftBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    -ms-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n}\r\n\r\n.fadeOutLeftBig {\r\n  -webkit-animation-name: fadeOutLeftBig;\r\n  animation-name: fadeOutLeftBig;\r\n}\r\n\r\n@-webkit-keyframes fadeOutRight {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(20px);\r\n    transform: translateX(20px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutRight {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(20px);\r\n    -ms-transform: translateX(20px);\r\n    transform: translateX(20px);\r\n  }\r\n}\r\n\r\n.fadeOutRight {\r\n  -webkit-animation-name: fadeOutRight;\r\n  animation-name: fadeOutRight;\r\n}\r\n\r\n@-webkit-keyframes fadeOutRightBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutRightBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    -ms-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n}\r\n\r\n.fadeOutRightBig {\r\n  -webkit-animation-name: fadeOutRightBig;\r\n  animation-name: fadeOutRightBig;\r\n}\r\n\r\n@-webkit-keyframes fadeOutUp {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-20px);\r\n    transform: translateY(-20px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutUp {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-20px);\r\n    -ms-transform: translateY(-20px);\r\n    transform: translateY(-20px);\r\n  }\r\n}\r\n\r\n.fadeOutUp {\r\n  -webkit-animation-name: fadeOutUp;\r\n  animation-name: fadeOutUp;\r\n}\r\n\r\n@-webkit-keyframes fadeOutUpBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n}\r\n\r\n@keyframes fadeOutUpBig {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    -ms-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n}\r\n\r\n.fadeOutUpBig {\r\n  -webkit-animation-name: fadeOutUpBig;\r\n  animation-name: fadeOutUpBig;\r\n}\r\n\r\n@-webkit-keyframes flip {\r\n  0% {\r\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\r\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\r\n    -webkit-animation-timing-function: ease-out;\r\n    animation-timing-function: ease-out;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\r\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\r\n    -webkit-animation-timing-function: ease-out;\r\n    animation-timing-function: ease-out;\r\n  }\r\n\r\n  50% {\r\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\r\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\r\n    -webkit-animation-timing-function: ease-in;\r\n    animation-timing-function: ease-in;\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\r\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\r\n    -webkit-animation-timing-function: ease-in;\r\n    animation-timing-function: ease-in;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\r\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\r\n    -webkit-animation-timing-function: ease-in;\r\n    animation-timing-function: ease-in;\r\n  }\r\n}\r\n\r\n@keyframes flip {\r\n  0% {\r\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\r\n    -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\r\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\r\n    -webkit-animation-timing-function: ease-out;\r\n    animation-timing-function: ease-out;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\r\n    -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\r\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\r\n    -webkit-animation-timing-function: ease-out;\r\n    animation-timing-function: ease-out;\r\n  }\r\n\r\n  50% {\r\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\r\n    -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\r\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\r\n    -webkit-animation-timing-function: ease-in;\r\n    animation-timing-function: ease-in;\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\r\n    -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\r\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\r\n    -webkit-animation-timing-function: ease-in;\r\n    animation-timing-function: ease-in;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\r\n    -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\r\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\r\n    -webkit-animation-timing-function: ease-in;\r\n    animation-timing-function: ease-in;\r\n  }\r\n}\r\n\r\n.animated.flip {\r\n  -webkit-backface-visibility: visible;\r\n  -ms-backface-visibility: visible;\r\n  backface-visibility: visible;\r\n  -webkit-animation-name: flip;\r\n  animation-name: flip;\r\n}\r\n\r\n@-webkit-keyframes flipInX {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateX(90deg);\r\n    transform: perspective(400px) rotateX(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: perspective(400px) rotateX(-10deg);\r\n    transform: perspective(400px) rotateX(-10deg);\r\n  }\r\n\r\n  70% {\r\n    -webkit-transform: perspective(400px) rotateX(10deg);\r\n    transform: perspective(400px) rotateX(10deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateX(0deg);\r\n    transform: perspective(400px) rotateX(0deg);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes flipInX {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateX(90deg);\r\n    -ms-transform: perspective(400px) rotateX(90deg);\r\n    transform: perspective(400px) rotateX(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: perspective(400px) rotateX(-10deg);\r\n    -ms-transform: perspective(400px) rotateX(-10deg);\r\n    transform: perspective(400px) rotateX(-10deg);\r\n  }\r\n\r\n  70% {\r\n    -webkit-transform: perspective(400px) rotateX(10deg);\r\n    -ms-transform: perspective(400px) rotateX(10deg);\r\n    transform: perspective(400px) rotateX(10deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateX(0deg);\r\n    -ms-transform: perspective(400px) rotateX(0deg);\r\n    transform: perspective(400px) rotateX(0deg);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.flipInX {\r\n  -webkit-backface-visibility: visible !important;\r\n  -ms-backface-visibility: visible !important;\r\n  backface-visibility: visible !important;\r\n  -webkit-animation-name: flipInX;\r\n  animation-name: flipInX;\r\n}\r\n\r\n@-webkit-keyframes flipInY {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateY(90deg);\r\n    transform: perspective(400px) rotateY(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: perspective(400px) rotateY(-10deg);\r\n    transform: perspective(400px) rotateY(-10deg);\r\n  }\r\n\r\n  70% {\r\n    -webkit-transform: perspective(400px) rotateY(10deg);\r\n    transform: perspective(400px) rotateY(10deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateY(0deg);\r\n    transform: perspective(400px) rotateY(0deg);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes flipInY {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateY(90deg);\r\n    -ms-transform: perspective(400px) rotateY(90deg);\r\n    transform: perspective(400px) rotateY(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: perspective(400px) rotateY(-10deg);\r\n    -ms-transform: perspective(400px) rotateY(-10deg);\r\n    transform: perspective(400px) rotateY(-10deg);\r\n  }\r\n\r\n  70% {\r\n    -webkit-transform: perspective(400px) rotateY(10deg);\r\n    -ms-transform: perspective(400px) rotateY(10deg);\r\n    transform: perspective(400px) rotateY(10deg);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateY(0deg);\r\n    -ms-transform: perspective(400px) rotateY(0deg);\r\n    transform: perspective(400px) rotateY(0deg);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.flipInY {\r\n  -webkit-backface-visibility: visible !important;\r\n  -ms-backface-visibility: visible !important;\r\n  backface-visibility: visible !important;\r\n  -webkit-animation-name: flipInY;\r\n  animation-name: flipInY;\r\n}\r\n\r\n@-webkit-keyframes flipOutX {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateX(0deg);\r\n    transform: perspective(400px) rotateX(0deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateX(90deg);\r\n    transform: perspective(400px) rotateX(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes flipOutX {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateX(0deg);\r\n    -ms-transform: perspective(400px) rotateX(0deg);\r\n    transform: perspective(400px) rotateX(0deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateX(90deg);\r\n    -ms-transform: perspective(400px) rotateX(90deg);\r\n    transform: perspective(400px) rotateX(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.flipOutX {\r\n  -webkit-animation-name: flipOutX;\r\n  animation-name: flipOutX;\r\n  -webkit-backface-visibility: visible !important;\r\n  -ms-backface-visibility: visible !important;\r\n  backface-visibility: visible !important;\r\n}\r\n\r\n@-webkit-keyframes flipOutY {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateY(0deg);\r\n    transform: perspective(400px) rotateY(0deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateY(90deg);\r\n    transform: perspective(400px) rotateY(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes flipOutY {\r\n  0% {\r\n    -webkit-transform: perspective(400px) rotateY(0deg);\r\n    -ms-transform: perspective(400px) rotateY(0deg);\r\n    transform: perspective(400px) rotateY(0deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: perspective(400px) rotateY(90deg);\r\n    -ms-transform: perspective(400px) rotateY(90deg);\r\n    transform: perspective(400px) rotateY(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.flipOutY {\r\n  -webkit-backface-visibility: visible !important;\r\n  -ms-backface-visibility: visible !important;\r\n  backface-visibility: visible !important;\r\n  -webkit-animation-name: flipOutY;\r\n  animation-name: flipOutY;\r\n}\r\n\r\n@-webkit-keyframes lightSpeedIn {\r\n  0% {\r\n    -webkit-transform: translateX(100%) skewX(-30deg);\r\n    transform: translateX(100%) skewX(-30deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: translateX(-20%) skewX(30deg);\r\n    transform: translateX(-20%) skewX(30deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateX(0%) skewX(-15deg);\r\n    transform: translateX(0%) skewX(-15deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0%) skewX(0deg);\r\n    transform: translateX(0%) skewX(0deg);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes lightSpeedIn {\r\n  0% {\r\n    -webkit-transform: translateX(100%) skewX(-30deg);\r\n    -ms-transform: translateX(100%) skewX(-30deg);\r\n    transform: translateX(100%) skewX(-30deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  60% {\r\n    -webkit-transform: translateX(-20%) skewX(30deg);\r\n    -ms-transform: translateX(-20%) skewX(30deg);\r\n    transform: translateX(-20%) skewX(30deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: translateX(0%) skewX(-15deg);\r\n    -ms-transform: translateX(0%) skewX(-15deg);\r\n    transform: translateX(0%) skewX(-15deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0%) skewX(0deg);\r\n    -ms-transform: translateX(0%) skewX(0deg);\r\n    transform: translateX(0%) skewX(0deg);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.lightSpeedIn {\r\n  -webkit-animation-name: lightSpeedIn;\r\n  animation-name: lightSpeedIn;\r\n  -webkit-animation-timing-function: ease-out;\r\n  animation-timing-function: ease-out;\r\n}\r\n\r\n@-webkit-keyframes lightSpeedOut {\r\n  0% {\r\n    -webkit-transform: translateX(0%) skewX(0deg);\r\n    transform: translateX(0%) skewX(0deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(100%) skewX(-30deg);\r\n    transform: translateX(100%) skewX(-30deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes lightSpeedOut {\r\n  0% {\r\n    -webkit-transform: translateX(0%) skewX(0deg);\r\n    -ms-transform: translateX(0%) skewX(0deg);\r\n    transform: translateX(0%) skewX(0deg);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(100%) skewX(-30deg);\r\n    -ms-transform: translateX(100%) skewX(-30deg);\r\n    transform: translateX(100%) skewX(-30deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.lightSpeedOut {\r\n  -webkit-animation-name: lightSpeedOut;\r\n  animation-name: lightSpeedOut;\r\n  -webkit-animation-timing-function: ease-in;\r\n  animation-timing-function: ease-in;\r\n}\r\n\r\n@-webkit-keyframes rotateIn {\r\n  0% {\r\n    -webkit-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(-200deg);\r\n    transform: rotate(-200deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes rotateIn {\r\n  0% {\r\n    -webkit-transform-origin: center center;\r\n    -ms-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(-200deg);\r\n    -ms-transform: rotate(-200deg);\r\n    transform: rotate(-200deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: center center;\r\n    -ms-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.rotateIn {\r\n  -webkit-animation-name: rotateIn;\r\n  animation-name: rotateIn;\r\n}\r\n\r\n@-webkit-keyframes rotateInDownLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes rotateInDownLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    -ms-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.rotateInDownLeft {\r\n  -webkit-animation-name: rotateInDownLeft;\r\n  animation-name: rotateInDownLeft;\r\n}\r\n\r\n@-webkit-keyframes rotateInDownRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes rotateInDownRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    -ms-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.rotateInDownRight {\r\n  -webkit-animation-name: rotateInDownRight;\r\n  animation-name: rotateInDownRight;\r\n}\r\n\r\n@-webkit-keyframes rotateInUpLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes rotateInUpLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    -ms-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.rotateInUpLeft {\r\n  -webkit-animation-name: rotateInUpLeft;\r\n  animation-name: rotateInUpLeft;\r\n}\r\n\r\n@-webkit-keyframes rotateInUpRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n@keyframes rotateInUpRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    -ms-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n}\r\n\r\n.rotateInUpRight {\r\n  -webkit-animation-name: rotateInUpRight;\r\n  animation-name: rotateInUpRight;\r\n}\r\n\r\n@-webkit-keyframes rotateOut {\r\n  0% {\r\n    -webkit-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(200deg);\r\n    transform: rotate(200deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes rotateOut {\r\n  0% {\r\n    -webkit-transform-origin: center center;\r\n    -ms-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: center center;\r\n    -ms-transform-origin: center center;\r\n    transform-origin: center center;\r\n    -webkit-transform: rotate(200deg);\r\n    -ms-transform: rotate(200deg);\r\n    transform: rotate(200deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.rotateOut {\r\n  -webkit-animation-name: rotateOut;\r\n  animation-name: rotateOut;\r\n}\r\n\r\n@-webkit-keyframes rotateOutDownLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes rotateOutDownLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    -ms-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.rotateOutDownLeft {\r\n  -webkit-animation-name: rotateOutDownLeft;\r\n  animation-name: rotateOutDownLeft;\r\n}\r\n\r\n@-webkit-keyframes rotateOutDownRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes rotateOutDownRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    -ms-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.rotateOutDownRight {\r\n  -webkit-animation-name: rotateOutDownRight;\r\n  animation-name: rotateOutDownRight;\r\n}\r\n\r\n@-webkit-keyframes rotateOutUpLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes rotateOutUpLeft {\r\n  0% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: left bottom;\r\n    -ms-transform-origin: left bottom;\r\n    transform-origin: left bottom;\r\n    -webkit-transform: rotate(-90deg);\r\n    -ms-transform: rotate(-90deg);\r\n    transform: rotate(-90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.rotateOutUpLeft {\r\n  -webkit-animation-name: rotateOutUpLeft;\r\n  animation-name: rotateOutUpLeft;\r\n}\r\n\r\n@-webkit-keyframes rotateOutUpRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes rotateOutUpRight {\r\n  0% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    opacity: 1;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform-origin: right bottom;\r\n    -ms-transform-origin: right bottom;\r\n    transform-origin: right bottom;\r\n    -webkit-transform: rotate(90deg);\r\n    -ms-transform: rotate(90deg);\r\n    transform: rotate(90deg);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.rotateOutUpRight {\r\n  -webkit-animation-name: rotateOutUpRight;\r\n  animation-name: rotateOutUpRight;\r\n}\r\n\r\n@-webkit-keyframes slideInDown {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n@keyframes slideInDown {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    -ms-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n}\r\n\r\n.slideInDown {\r\n  -webkit-animation-name: slideInDown;\r\n  animation-name: slideInDown;\r\n}\r\n\r\n@-webkit-keyframes slideInLeft {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes slideInLeft {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    -ms-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.slideInLeft {\r\n  -webkit-animation-name: slideInLeft;\r\n  animation-name: slideInLeft;\r\n}\r\n\r\n@-webkit-keyframes slideInRight {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n@keyframes slideInRight {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    -ms-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n}\r\n\r\n.slideInRight {\r\n  -webkit-animation-name: slideInRight;\r\n  animation-name: slideInRight;\r\n}\r\n\r\n@-webkit-keyframes slideOutLeft {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n}\r\n\r\n@keyframes slideOutLeft {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-2000px);\r\n    -ms-transform: translateX(-2000px);\r\n    transform: translateX(-2000px);\r\n  }\r\n}\r\n\r\n.slideOutLeft {\r\n  -webkit-animation-name: slideOutLeft;\r\n  animation-name: slideOutLeft;\r\n}\r\n\r\n@-webkit-keyframes slideOutRight {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n}\r\n\r\n@keyframes slideOutRight {\r\n  0% {\r\n    -webkit-transform: translateX(0);\r\n    -ms-transform: translateX(0);\r\n    transform: translateX(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(2000px);\r\n    -ms-transform: translateX(2000px);\r\n    transform: translateX(2000px);\r\n  }\r\n}\r\n\r\n.slideOutRight {\r\n  -webkit-animation-name: slideOutRight;\r\n  animation-name: slideOutRight;\r\n}\r\n\r\n@-webkit-keyframes slideOutUp {\r\n  0% {\r\n    -webkit-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n}\r\n\r\n@keyframes slideOutUp {\r\n  0% {\r\n    -webkit-transform: translateY(0);\r\n    -ms-transform: translateY(0);\r\n    transform: translateY(0);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateY(-2000px);\r\n    -ms-transform: translateY(-2000px);\r\n    transform: translateY(-2000px);\r\n  }\r\n}\r\n\r\n.slideOutUp {\r\n  -webkit-animation-name: slideOutUp;\r\n  animation-name: slideOutUp;\r\n}\r\n\r\n@-webkit-keyframes hinge {\r\n  0% {\r\n    -webkit-transform: rotate(0);\r\n    transform: rotate(0);\r\n    -webkit-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  20%, 60% {\r\n    -webkit-transform: rotate(80deg);\r\n    transform: rotate(80deg);\r\n    -webkit-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: rotate(60deg);\r\n    transform: rotate(60deg);\r\n    -webkit-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: rotate(60deg) translateY(0);\r\n    transform: rotate(60deg) translateY(0);\r\n    opacity: 1;\r\n    -webkit-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(700px);\r\n    transform: translateY(700px);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n@keyframes hinge {\r\n  0% {\r\n    -webkit-transform: rotate(0);\r\n    -ms-transform: rotate(0);\r\n    transform: rotate(0);\r\n    -webkit-transform-origin: top left;\r\n    -ms-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  20%, 60% {\r\n    -webkit-transform: rotate(80deg);\r\n    -ms-transform: rotate(80deg);\r\n    transform: rotate(80deg);\r\n    -webkit-transform-origin: top left;\r\n    -ms-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  40% {\r\n    -webkit-transform: rotate(60deg);\r\n    -ms-transform: rotate(60deg);\r\n    transform: rotate(60deg);\r\n    -webkit-transform-origin: top left;\r\n    -ms-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  80% {\r\n    -webkit-transform: rotate(60deg) translateY(0);\r\n    -ms-transform: rotate(60deg) translateY(0);\r\n    transform: rotate(60deg) translateY(0);\r\n    opacity: 1;\r\n    -webkit-transform-origin: top left;\r\n    -ms-transform-origin: top left;\r\n    transform-origin: top left;\r\n    -webkit-animation-timing-function: ease-in-out;\r\n    animation-timing-function: ease-in-out;\r\n  }\r\n\r\n  100% {\r\n    -webkit-transform: translateY(700px);\r\n    -ms-transform: translateY(700px);\r\n    transform: translateY(700px);\r\n    opacity: 0;\r\n  }\r\n}\r\n\r\n.hinge {\r\n  -webkit-animation-name: hinge;\r\n  animation-name: hinge;\r\n}\r\n\r\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\r\n\r\n@-webkit-keyframes rollIn {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-100%) rotate(-120deg);\r\n    transform: translateX(-100%) rotate(-120deg);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0px) rotate(0deg);\r\n    transform: translateX(0px) rotate(0deg);\r\n  }\r\n}\r\n\r\n@keyframes rollIn {\r\n  0% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(-100%) rotate(-120deg);\r\n    -ms-transform: translateX(-100%) rotate(-120deg);\r\n    transform: translateX(-100%) rotate(-120deg);\r\n  }\r\n\r\n  100% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0px) rotate(0deg);\r\n    -ms-transform: translateX(0px) rotate(0deg);\r\n    transform: translateX(0px) rotate(0deg);\r\n  }\r\n}\r\n\r\n.rollIn {\r\n  -webkit-animation-name: rollIn;\r\n  animation-name: rollIn;\r\n}\r\n\r\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\r\n\r\n@-webkit-keyframes rollOut {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0px) rotate(0deg);\r\n    transform: translateX(0px) rotate(0deg);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(100%) rotate(120deg);\r\n    transform: translateX(100%) rotate(120deg);\r\n  }\r\n}\r\n\r\n@keyframes rollOut {\r\n  0% {\r\n    opacity: 1;\r\n    -webkit-transform: translateX(0px) rotate(0deg);\r\n    -ms-transform: translateX(0px) rotate(0deg);\r\n    transform: translateX(0px) rotate(0deg);\r\n  }\r\n\r\n  100% {\r\n    opacity: 0;\r\n    -webkit-transform: translateX(100%) rotate(120deg);\r\n    -ms-transform: translateX(100%) rotate(120deg);\r\n    transform: translateX(100%) rotate(120deg);\r\n  }\r\n}\r\n\r\n.rollOut {\r\n  -webkit-animation-name: rollOut;\r\n  animation-name: rollOut;\r\n}"
  },
  {
    "path": "docs/assets/css/github-markdown.css",
    "content": "@media (prefers-color-scheme: dark) {\n  .markdown-body {\n    color-scheme: dark;\n    --color-prettylights-syntax-comment: #8b949e;\n    --color-prettylights-syntax-constant: #79c0ff;\n    --color-prettylights-syntax-entity: #d2a8ff;\n    --color-prettylights-syntax-storage-modifier-import: #c9d1d9;\n    --color-prettylights-syntax-entity-tag: #7ee787;\n    --color-prettylights-syntax-keyword: #ff7b72;\n    --color-prettylights-syntax-string: #a5d6ff;\n    --color-prettylights-syntax-variable: #ffa657;\n    --color-prettylights-syntax-brackethighlighter-unmatched: #f85149;\n    --color-prettylights-syntax-invalid-illegal-text: #f0f6fc;\n    --color-prettylights-syntax-invalid-illegal-bg: #8e1519;\n    --color-prettylights-syntax-carriage-return-text: #f0f6fc;\n    --color-prettylights-syntax-carriage-return-bg: #b62324;\n    --color-prettylights-syntax-string-regexp: #7ee787;\n    --color-prettylights-syntax-markup-list: #f2cc60;\n    --color-prettylights-syntax-markup-heading: #1f6feb;\n    --color-prettylights-syntax-markup-italic: #c9d1d9;\n    --color-prettylights-syntax-markup-bold: #c9d1d9;\n    --color-prettylights-syntax-markup-deleted-text: #ffdcd7;\n    --color-prettylights-syntax-markup-deleted-bg: #67060c;\n    --color-prettylights-syntax-markup-inserted-text: #aff5b4;\n    --color-prettylights-syntax-markup-inserted-bg: #033a16;\n    --color-prettylights-syntax-markup-changed-text: #ffdfb6;\n    --color-prettylights-syntax-markup-changed-bg: #5a1e02;\n    --color-prettylights-syntax-markup-ignored-text: #c9d1d9;\n    --color-prettylights-syntax-markup-ignored-bg: #1158c7;\n    --color-prettylights-syntax-meta-diff-range: #d2a8ff;\n    --color-prettylights-syntax-brackethighlighter-angle: #8b949e;\n    --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58;\n    --color-prettylights-syntax-constant-other-reference-link: #a5d6ff;\n    --color-fg-default: #c9d1d9;\n    --color-fg-muted: #8b949e;\n    --color-fg-subtle: #484f58;\n    --color-canvas-default: #0d1117;\n    --color-canvas-subtle: #161b22;\n    --color-border-default: #30363d;\n    --color-border-muted: #21262d;\n    --color-neutral-muted: rgba(110,118,129,0.4);\n    --color-accent-fg: #58a6ff;\n    --color-accent-emphasis: #1f6feb;\n    --color-attention-subtle: rgba(187,128,9,0.15);\n    --color-danger-fg: #f85149;\n  }\n}\n\n@media (prefers-color-scheme: light) {\n  .markdown-body {\n    color-scheme: light;\n    --color-prettylights-syntax-comment: #6e7781;\n    --color-prettylights-syntax-constant: #0550ae;\n    --color-prettylights-syntax-entity: #8250df;\n    --color-prettylights-syntax-storage-modifier-import: #24292f;\n    --color-prettylights-syntax-entity-tag: #116329;\n    --color-prettylights-syntax-keyword: #cf222e;\n    --color-prettylights-syntax-string: #0a3069;\n    --color-prettylights-syntax-variable: #953800;\n    --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\n    --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\n    --color-prettylights-syntax-invalid-illegal-bg: #82071e;\n    --color-prettylights-syntax-carriage-return-text: #f6f8fa;\n    --color-prettylights-syntax-carriage-return-bg: #cf222e;\n    --color-prettylights-syntax-string-regexp: #116329;\n    --color-prettylights-syntax-markup-list: #3b2300;\n    --color-prettylights-syntax-markup-heading: #0550ae;\n    --color-prettylights-syntax-markup-italic: #24292f;\n    --color-prettylights-syntax-markup-bold: #24292f;\n    --color-prettylights-syntax-markup-deleted-text: #82071e;\n    --color-prettylights-syntax-markup-deleted-bg: #FFEBE9;\n    --color-prettylights-syntax-markup-inserted-text: #116329;\n    --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\n    --color-prettylights-syntax-markup-changed-text: #953800;\n    --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\n    --color-prettylights-syntax-markup-ignored-text: #eaeef2;\n    --color-prettylights-syntax-markup-ignored-bg: #0550ae;\n    --color-prettylights-syntax-meta-diff-range: #8250df;\n    --color-prettylights-syntax-brackethighlighter-angle: #57606a;\n    --color-prettylights-syntax-sublimelinter-gutter-mark: #8c959f;\n    --color-prettylights-syntax-constant-other-reference-link: #0a3069;\n    --color-fg-default: #24292f;\n    --color-fg-muted: #57606a;\n    --color-fg-subtle: #6e7781;\n    --color-canvas-default: #ffffff;\n    --color-canvas-subtle: #f6f8fa;\n    --color-border-default: #d0d7de;\n    --color-border-muted: hsla(210,18%,87%,1);\n    --color-neutral-muted: rgba(175,184,193,0.2);\n    --color-accent-fg: #0969da;\n    --color-accent-emphasis: #0969da;\n    --color-attention-subtle: #fff8c5;\n    --color-danger-fg: #cf222e;\n  }\n}\n\n.markdown-body {\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n  margin: 0;\n  color: var(--color-fg-default);\n  background-color: var(--color-canvas-default);\n  font-family: -apple-system,BlinkMacSystemFont,\"Segoe UI\",Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";\n  font-size: 16px;\n  line-height: 1.5;\n  word-wrap: break-word;\n}\n\n.markdown-body .octicon {\n  display: inline-block;\n  fill: currentColor;\n  vertical-align: text-bottom;\n}\n\n.markdown-body h1:hover .anchor .octicon-link:before,\n.markdown-body h2:hover .anchor .octicon-link:before,\n.markdown-body h3:hover .anchor .octicon-link:before,\n.markdown-body h4:hover .anchor .octicon-link:before,\n.markdown-body h5:hover .anchor .octicon-link:before,\n.markdown-body h6:hover .anchor .octicon-link:before {\n  width: 16px;\n  height: 16px;\n  content: ' ';\n  display: inline-block;\n  background-color: currentColor;\n  -webkit-mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\n  mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\n}\n\n.markdown-body details,\n.markdown-body figcaption,\n.markdown-body figure {\n  display: block;\n}\n\n.markdown-body summary {\n  display: list-item;\n}\n\n.markdown-body [hidden] {\n  display: none !important;\n}\n\n.markdown-body a {\n  background-color: transparent;\n  color: var(--color-accent-fg);\n  text-decoration: none;\n}\n\n.markdown-body a:active,\n.markdown-body a:hover {\n  outline-width: 0;\n}\n\n.markdown-body abbr[title] {\n  border-bottom: none;\n  text-decoration: underline dotted;\n}\n\n.markdown-body b,\n.markdown-body strong {\n  font-weight: 600;\n}\n\n.markdown-body dfn {\n  font-style: italic;\n}\n\n.markdown-body h1 {\n  margin: .67em 0;\n  font-weight: 600;\n  padding-bottom: .3em;\n  font-size: 2em;\n  border-bottom: 1px solid var(--color-border-muted);\n}\n\n.markdown-body mark {\n  background-color: var(--color-attention-subtle);\n  color: var(--color-text-primary);\n}\n\n.markdown-body small {\n  font-size: 90%;\n}\n\n.markdown-body sub,\n.markdown-body sup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\n.markdown-body sub {\n  bottom: -0.25em;\n}\n\n.markdown-body sup {\n  top: -0.5em;\n}\n\n.markdown-body img {\n  border-style: none;\n  max-width: 100%;\n  box-sizing: content-box;\n  background-color: var(--color-canvas-default);\n}\n\n.markdown-body code,\n.markdown-body kbd,\n.markdown-body pre,\n.markdown-body samp {\n  font-family: monospace,monospace;\n  font-size: 1em;\n}\n\n.markdown-body figure {\n  margin: 1em 40px;\n}\n\n.markdown-body hr {\n  box-sizing: content-box;\n  overflow: hidden;\n  background: transparent;\n  border-bottom: 1px solid var(--color-border-muted);\n  height: .25em;\n  padding: 0;\n  margin: 24px 0;\n  background-color: var(--color-border-default);\n  border: 0;\n}\n\n.markdown-body input {\n  font: inherit;\n  margin: 0;\n  overflow: visible;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\n.markdown-body [type=button],\n.markdown-body [type=reset],\n.markdown-body [type=submit] {\n  -webkit-appearance: button;\n}\n\n.markdown-body [type=button]::-moz-focus-inner,\n.markdown-body [type=reset]::-moz-focus-inner,\n.markdown-body [type=submit]::-moz-focus-inner {\n  border-style: none;\n  padding: 0;\n}\n\n.markdown-body [type=button]:-moz-focusring,\n.markdown-body [type=reset]:-moz-focusring,\n.markdown-body [type=submit]:-moz-focusring {\n  outline: 1px dotted ButtonText;\n}\n\n.markdown-body [type=checkbox],\n.markdown-body [type=radio] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\n.markdown-body [type=number]::-webkit-inner-spin-button,\n.markdown-body [type=number]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n.markdown-body [type=search] {\n  -webkit-appearance: textfield;\n  outline-offset: -2px;\n}\n\n.markdown-body [type=search]::-webkit-search-cancel-button,\n.markdown-body [type=search]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n.markdown-body ::-webkit-input-placeholder {\n  color: inherit;\n  opacity: .54;\n}\n\n.markdown-body ::-webkit-file-upload-button {\n  -webkit-appearance: button;\n  font: inherit;\n}\n\n.markdown-body a:hover {\n  text-decoration: underline;\n}\n\n.markdown-body hr::before {\n  display: table;\n  content: \"\";\n}\n\n.markdown-body hr::after {\n  display: table;\n  clear: both;\n  content: \"\";\n}\n\n.markdown-body table {\n  border-spacing: 0;\n  border-collapse: collapse;\n  display: block;\n  width: max-content;\n  max-width: 100%;\n  overflow: auto;\n}\n\n.markdown-body td,\n.markdown-body th {\n  padding: 0;\n}\n\n.markdown-body details summary {\n  cursor: pointer;\n}\n\n.markdown-body details:not([open])>*:not(summary) {\n  display: none !important;\n}\n\n.markdown-body kbd {\n  display: inline-block;\n  padding: 3px 5px;\n  font: 11px ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;\n  line-height: 10px;\n  color: var(--color-fg-default);\n  vertical-align: middle;\n  background-color: var(--color-canvas-subtle);\n  border: solid 1px var(--color-neutral-muted);\n  border-bottom-color: var(--color-neutral-muted);\n  border-radius: 6px;\n  box-shadow: inset 0 -1px 0 var(--color-neutral-muted);\n}\n\n.markdown-body h1,\n.markdown-body h2,\n.markdown-body h3,\n.markdown-body h4,\n.markdown-body h5,\n.markdown-body h6 {\n  margin-top: 24px;\n  margin-bottom: 16px;\n  font-weight: 600;\n  line-height: 1.25;\n}\n\n.markdown-body h2 {\n  font-weight: 600;\n  padding-bottom: .3em;\n  font-size: 1.5em;\n  border-bottom: 1px solid var(--color-border-muted);\n}\n\n.markdown-body h3 {\n  font-weight: 600;\n  font-size: 1.25em;\n}\n\n.markdown-body h4 {\n  font-weight: 600;\n  font-size: 1em;\n}\n\n.markdown-body h5 {\n  font-weight: 600;\n  font-size: .875em;\n}\n\n.markdown-body h6 {\n  font-weight: 600;\n  font-size: .85em;\n  color: var(--color-fg-muted);\n}\n\n.markdown-body p {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n\n.markdown-body blockquote {\n  margin: 0;\n  padding: 0 1em;\n  color: var(--color-fg-muted);\n  border-left: .25em solid var(--color-border-default);\n}\n\n.markdown-body ul,\n.markdown-body ol {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-left: 2em;\n}\n\n.markdown-body ol ol,\n.markdown-body ul ol {\n  list-style-type: lower-roman;\n}\n\n.markdown-body ul ul ol,\n.markdown-body ul ol ol,\n.markdown-body ol ul ol,\n.markdown-body ol ol ol {\n  list-style-type: lower-alpha;\n}\n\n.markdown-body dd {\n  margin-left: 0;\n}\n\n.markdown-body tt,\n.markdown-body code {\n  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;\n  font-size: 12px;\n}\n\n.markdown-body pre {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;\n  font-size: 12px;\n  word-wrap: normal;\n}\n\n.markdown-body .octicon {\n  display: inline-block;\n  overflow: visible !important;\n  vertical-align: text-bottom;\n  fill: currentColor;\n}\n\n.markdown-body ::placeholder {\n  color: var(--color-fg-subtle);\n  opacity: 1;\n}\n\n.markdown-body input::-webkit-outer-spin-button,\n.markdown-body input::-webkit-inner-spin-button {\n  margin: 0;\n  -webkit-appearance: none;\n  appearance: none;\n}\n\n.markdown-body .pl-c {\n  color: var(--color-prettylights-syntax-comment);\n}\n\n.markdown-body .pl-c1,\n.markdown-body .pl-s .pl-v {\n  color: var(--color-prettylights-syntax-constant);\n}\n\n.markdown-body .pl-e,\n.markdown-body .pl-en {\n  color: var(--color-prettylights-syntax-entity);\n}\n\n.markdown-body .pl-smi,\n.markdown-body .pl-s .pl-s1 {\n  color: var(--color-prettylights-syntax-storage-modifier-import);\n}\n\n.markdown-body .pl-ent {\n  color: var(--color-prettylights-syntax-entity-tag);\n}\n\n.markdown-body .pl-k {\n  color: var(--color-prettylights-syntax-keyword);\n}\n\n.markdown-body .pl-s,\n.markdown-body .pl-pds,\n.markdown-body .pl-s .pl-pse .pl-s1,\n.markdown-body .pl-sr,\n.markdown-body .pl-sr .pl-cce,\n.markdown-body .pl-sr .pl-sre,\n.markdown-body .pl-sr .pl-sra {\n  color: var(--color-prettylights-syntax-string);\n}\n\n.markdown-body .pl-v,\n.markdown-body .pl-smw {\n  color: var(--color-prettylights-syntax-variable);\n}\n\n.markdown-body .pl-bu {\n  color: var(--color-prettylights-syntax-brackethighlighter-unmatched);\n}\n\n.markdown-body .pl-ii {\n  color: var(--color-prettylights-syntax-invalid-illegal-text);\n  background-color: var(--color-prettylights-syntax-invalid-illegal-bg);\n}\n\n.markdown-body .pl-c2 {\n  color: var(--color-prettylights-syntax-carriage-return-text);\n  background-color: var(--color-prettylights-syntax-carriage-return-bg);\n}\n\n.markdown-body .pl-sr .pl-cce {\n  font-weight: bold;\n  color: var(--color-prettylights-syntax-string-regexp);\n}\n\n.markdown-body .pl-ml {\n  color: var(--color-prettylights-syntax-markup-list);\n}\n\n.markdown-body .pl-mh,\n.markdown-body .pl-mh .pl-en,\n.markdown-body .pl-ms {\n  font-weight: bold;\n  color: var(--color-prettylights-syntax-markup-heading);\n}\n\n.markdown-body .pl-mi {\n  font-style: italic;\n  color: var(--color-prettylights-syntax-markup-italic);\n}\n\n.markdown-body .pl-mb {\n  font-weight: bold;\n  color: var(--color-prettylights-syntax-markup-bold);\n}\n\n.markdown-body .pl-md {\n  color: var(--color-prettylights-syntax-markup-deleted-text);\n  background-color: var(--color-prettylights-syntax-markup-deleted-bg);\n}\n\n.markdown-body .pl-mi1 {\n  color: var(--color-prettylights-syntax-markup-inserted-text);\n  background-color: var(--color-prettylights-syntax-markup-inserted-bg);\n}\n\n.markdown-body .pl-mc {\n  color: var(--color-prettylights-syntax-markup-changed-text);\n  background-color: var(--color-prettylights-syntax-markup-changed-bg);\n}\n\n.markdown-body .pl-mi2 {\n  color: var(--color-prettylights-syntax-markup-ignored-text);\n  background-color: var(--color-prettylights-syntax-markup-ignored-bg);\n}\n\n.markdown-body .pl-mdr {\n  font-weight: bold;\n  color: var(--color-prettylights-syntax-meta-diff-range);\n}\n\n.markdown-body .pl-ba {\n  color: var(--color-prettylights-syntax-brackethighlighter-angle);\n}\n\n.markdown-body .pl-sg {\n  color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);\n}\n\n.markdown-body .pl-corl {\n  text-decoration: underline;\n  color: var(--color-prettylights-syntax-constant-other-reference-link);\n}\n\n.markdown-body [data-catalyst] {\n  display: block;\n}\n\n.markdown-body g-emoji {\n  font-family: \"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";\n  font-size: 1em;\n  font-style: normal !important;\n  font-weight: 400;\n  line-height: 1;\n  vertical-align: -0.075em;\n}\n\n.markdown-body g-emoji img {\n  width: 1em;\n  height: 1em;\n}\n\n.markdown-body::before {\n  display: table;\n  content: \"\";\n}\n\n.markdown-body::after {\n  display: table;\n  clear: both;\n  content: \"\";\n}\n\n.markdown-body>*:first-child {\n  margin-top: 0 !important;\n}\n\n.markdown-body>*:last-child {\n  margin-bottom: 0 !important;\n}\n\n.markdown-body a:not([href]) {\n  color: inherit;\n  text-decoration: none;\n}\n\n.markdown-body .absent {\n  color: var(--color-danger-fg);\n}\n\n.markdown-body .anchor {\n  float: left;\n  padding-right: 4px;\n  margin-left: -20px;\n  line-height: 1;\n}\n\n.markdown-body .anchor:focus {\n  outline: none;\n}\n\n.markdown-body p,\n.markdown-body blockquote,\n.markdown-body ul,\n.markdown-body ol,\n.markdown-body dl,\n.markdown-body table,\n.markdown-body pre,\n.markdown-body details {\n  margin-top: 0;\n  margin-bottom: 16px;\n}\n\n.markdown-body blockquote>:first-child {\n  margin-top: 0;\n}\n\n.markdown-body blockquote>:last-child {\n  margin-bottom: 0;\n}\n\n.markdown-body sup>a::before {\n  content: \"[\";\n}\n\n.markdown-body sup>a::after {\n  content: \"]\";\n}\n\n.markdown-body h1 .octicon-link,\n.markdown-body h2 .octicon-link,\n.markdown-body h3 .octicon-link,\n.markdown-body h4 .octicon-link,\n.markdown-body h5 .octicon-link,\n.markdown-body h6 .octicon-link {\n  color: var(--color-fg-default);\n  vertical-align: middle;\n  visibility: hidden;\n}\n\n.markdown-body h1:hover .anchor,\n.markdown-body h2:hover .anchor,\n.markdown-body h3:hover .anchor,\n.markdown-body h4:hover .anchor,\n.markdown-body h5:hover .anchor,\n.markdown-body h6:hover .anchor {\n  text-decoration: none;\n}\n\n.markdown-body h1:hover .anchor .octicon-link,\n.markdown-body h2:hover .anchor .octicon-link,\n.markdown-body h3:hover .anchor .octicon-link,\n.markdown-body h4:hover .anchor .octicon-link,\n.markdown-body h5:hover .anchor .octicon-link,\n.markdown-body h6:hover .anchor .octicon-link {\n  visibility: visible;\n}\n\n.markdown-body h1 tt,\n.markdown-body h1 code,\n.markdown-body h2 tt,\n.markdown-body h2 code,\n.markdown-body h3 tt,\n.markdown-body h3 code,\n.markdown-body h4 tt,\n.markdown-body h4 code,\n.markdown-body h5 tt,\n.markdown-body h5 code,\n.markdown-body h6 tt,\n.markdown-body h6 code {\n  padding: 0 .2em;\n  font-size: inherit;\n}\n\n.markdown-body ul.no-list,\n.markdown-body ol.no-list {\n  padding: 0;\n  list-style-type: none;\n}\n\n.markdown-body ol[type=\"1\"] {\n  list-style-type: decimal;\n}\n\n.markdown-body ol[type=a] {\n  list-style-type: lower-alpha;\n}\n\n.markdown-body ol[type=i] {\n  list-style-type: lower-roman;\n}\n\n.markdown-body div>ol:not([type]) {\n  list-style-type: decimal;\n}\n\n.markdown-body ul ul,\n.markdown-body ul ol,\n.markdown-body ol ol,\n.markdown-body ol ul {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body li>p {\n  margin-top: 16px;\n}\n\n.markdown-body li+li {\n  margin-top: .25em;\n}\n\n.markdown-body dl {\n  padding: 0;\n}\n\n.markdown-body dl dt {\n  padding: 0;\n  margin-top: 16px;\n  font-size: 1em;\n  font-style: italic;\n  font-weight: 600;\n}\n\n.markdown-body dl dd {\n  padding: 0 16px;\n  margin-bottom: 16px;\n}\n\n.markdown-body table th {\n  font-weight: 600;\n}\n\n.markdown-body table th,\n.markdown-body table td {\n  padding: 6px 13px;\n  border: 1px solid var(--color-border-default);\n}\n\n.markdown-body table tr {\n  background-color: var(--color-canvas-default);\n  border-top: 1px solid var(--color-border-muted);\n}\n\n.markdown-body table tr:nth-child(2n) {\n  background-color: var(--color-canvas-subtle);\n}\n\n.markdown-body table img {\n  background-color: transparent;\n}\n\n.markdown-body img[align=right] {\n  padding-left: 20px;\n}\n\n.markdown-body img[align=left] {\n  padding-right: 20px;\n}\n\n.markdown-body .emoji {\n  max-width: none;\n  vertical-align: text-top;\n  background-color: transparent;\n}\n\n.markdown-body span.frame {\n  display: block;\n  overflow: hidden;\n}\n\n.markdown-body span.frame>span {\n  display: block;\n  float: left;\n  width: auto;\n  padding: 7px;\n  margin: 13px 0 0;\n  overflow: hidden;\n  border: 1px solid var(--color-border-default);\n}\n\n.markdown-body span.frame span img {\n  display: block;\n  float: left;\n}\n\n.markdown-body span.frame span span {\n  display: block;\n  padding: 5px 0 0;\n  clear: both;\n  color: var(--color-fg-default);\n}\n\n.markdown-body span.align-center {\n  display: block;\n  overflow: hidden;\n  clear: both;\n}\n\n.markdown-body span.align-center>span {\n  display: block;\n  margin: 13px auto 0;\n  overflow: hidden;\n  text-align: center;\n}\n\n.markdown-body span.align-center span img {\n  margin: 0 auto;\n  text-align: center;\n}\n\n.markdown-body span.align-right {\n  display: block;\n  overflow: hidden;\n  clear: both;\n}\n\n.markdown-body span.align-right>span {\n  display: block;\n  margin: 13px 0 0;\n  overflow: hidden;\n  text-align: right;\n}\n\n.markdown-body span.align-right span img {\n  margin: 0;\n  text-align: right;\n}\n\n.markdown-body span.float-left {\n  display: block;\n  float: left;\n  margin-right: 13px;\n  overflow: hidden;\n}\n\n.markdown-body span.float-left span {\n  margin: 13px 0 0;\n}\n\n.markdown-body span.float-right {\n  display: block;\n  float: right;\n  margin-left: 13px;\n  overflow: hidden;\n}\n\n.markdown-body span.float-right>span {\n  display: block;\n  margin: 13px auto 0;\n  overflow: hidden;\n  text-align: right;\n}\n\n.markdown-body code,\n.markdown-body tt {\n  padding: .2em .4em;\n  margin: 0;\n  font-size: 85%;\n  background-color: var(--color-neutral-muted);\n  border-radius: 6px;\n}\n\n.markdown-body code br,\n.markdown-body tt br {\n  display: none;\n}\n\n.markdown-body del code {\n  text-decoration: inherit;\n}\n\n.markdown-body pre code {\n  font-size: 100%;\n}\n\n.markdown-body pre>code {\n  padding: 0;\n  margin: 0;\n  word-break: normal;\n  white-space: pre;\n  background: transparent;\n  border: 0;\n}\n\n.markdown-body .highlight {\n  margin-bottom: 16px;\n}\n\n.markdown-body .highlight pre {\n  margin-bottom: 0;\n  word-break: normal;\n}\n\n.markdown-body .highlight pre,\n.markdown-body pre {\n  padding: 16px;\n  overflow: auto;\n  font-size: 85%;\n  line-height: 1.45;\n  background-color: var(--color-canvas-subtle);\n  border-radius: 6px;\n}\n\n.markdown-body pre code,\n.markdown-body pre tt {\n  display: inline;\n  max-width: auto;\n  padding: 0;\n  margin: 0;\n  overflow: visible;\n  line-height: inherit;\n  word-wrap: normal;\n  background-color: transparent;\n  border: 0;\n}\n\n.markdown-body .csv-data td,\n.markdown-body .csv-data th {\n  padding: 5px;\n  overflow: hidden;\n  font-size: 12px;\n  line-height: 1;\n  text-align: left;\n  white-space: nowrap;\n}\n\n.markdown-body .csv-data .blob-num {\n  padding: 10px 8px 9px;\n  text-align: right;\n  background: var(--color-canvas-default);\n  border: 0;\n}\n\n.markdown-body .csv-data tr {\n  border-top: 0;\n}\n\n.markdown-body .csv-data th {\n  font-weight: 600;\n  background: var(--color-canvas-subtle);\n  border-top: 0;\n}\n\n.markdown-body .footnotes {\n  font-size: 12px;\n  color: var(--color-fg-muted);\n  border-top: 1px solid var(--color-border-default);\n}\n\n.markdown-body .footnotes ol {\n  padding-left: 16px;\n}\n\n.markdown-body .footnotes li {\n  position: relative;\n}\n\n.markdown-body .footnotes li:target::before {\n  position: absolute;\n  top: -8px;\n  right: -8px;\n  bottom: -8px;\n  left: -24px;\n  pointer-events: none;\n  content: \"\";\n  border: 2px solid var(--color-accent-emphasis);\n  border-radius: 6px;\n}\n\n.markdown-body .footnotes li:target {\n  color: var(--color-fg-default);\n}\n\n.markdown-body .footnotes .data-footnote-backref g-emoji {\n  font-family: monospace;\n}\n\n.markdown-body .task-list-item {\n  list-style-type: none;\n}\n\n.markdown-body .task-list-item label {\n  font-weight: 400;\n}\n\n.markdown-body .task-list-item.enabled label {\n  cursor: pointer;\n}\n\n.markdown-body .task-list-item+.task-list-item {\n  margin-top: 3px;\n}\n\n.markdown-body .task-list-item .handle {\n  display: none;\n}\n\n.markdown-body .task-list-item-checkbox {\n  margin: 0 .2em .25em -1.6em;\n  vertical-align: middle;\n}\n\n.markdown-body .contains-task-list:dir(rtl) .task-list-item-checkbox {\n  margin: 0 -1.6em .25em .2em;\n}\n\n.markdown-body ::-webkit-calendar-picker-indicator {\n  filter: invert(50%);\n}\n"
  },
  {
    "path": "docs/assets/css/jquery.accordion.css",
    "content": "/*!\n * jQuery Accordion 0.0.1\n * (c) 2014 Victor Fernandez <victor@vctrfrnndz.com>\n * MIT Licensed.\n */\n\n/* Requirements */\n\n[data-accordion] [data-content] {\n    overflow: hidden;\n    max-height: 0;\n}\n\n/* Basic Theme */\n\n[data-accordion-group] {\n  padding: 20px;\n  box-shadow: 0 0px 15px rgba(0,0,0,0.06);\n}\n\n[data-control] {\n  cursor: pointer;\n}\n\n[data-accordion] {\n    line-height: 1;\n}\n\n[data-control],\n[data-content] > * {\n    border-bottom: 1px solid #EEE;\n    padding: 10px;\n}\n\n[data-content] [data-accordion] {\n    border: 0;\n    padding: 0;\n}\n\n[data-accordion] [data-control] {\n    position: relative;\n    padding-right: 40px;\n}\n\n[data-accordion] > [data-control]:after {\n    content: \"\";\n    position: absolute;\n    right: 10px;\n    top: 12px;\n    font-size: 25px;\n    font-weight: 200;\n    color: #444;\n    height: 15px;\n    width: 24px;\n    background: url('../images/down.png') center center no-repeat;\n    background-size: 50%;\n}\n\n[data-accordion].open > [data-control]:after {\n    -webkit-transform: rotate(-180deg);\n    -ms-transform: rotate(-180deg);\n    transform: rotate(-180deg);\n}\n"
  },
  {
    "path": "docs/assets/css/magnific-popup.css",
    "content": "/* Magnific Popup CSS */\n.mfp-bg {\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 1042;\n  overflow: hidden;\n  position: fixed;\n  background: #0b0b0b;\n  opacity: 0.8; }\n\n.mfp-wrap {\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 1043;\n  position: fixed;\n  outline: none !important;\n  -webkit-backface-visibility: hidden; }\n\n.mfp-container {\n  text-align: center;\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  left: 0;\n  top: 0;\n  padding: 0 8px;\n  box-sizing: border-box; }\n\n.mfp-container:before {\n  content: '';\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle; }\n\n.mfp-align-top .mfp-container:before {\n  display: none; }\n\n.mfp-content {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n  margin: 0 auto;\n  text-align: left;\n  z-index: 1045; }\n\n.mfp-inline-holder .mfp-content,\n.mfp-ajax-holder .mfp-content {\n  width: 100%;\n  cursor: auto; }\n\n.mfp-ajax-cur {\n  cursor: progress; }\n\n.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {\n  cursor: -moz-zoom-out;\n  cursor: -webkit-zoom-out;\n  cursor: zoom-out; }\n\n.mfp-zoom {\n  cursor: pointer;\n  cursor: -webkit-zoom-in;\n  cursor: -moz-zoom-in;\n  cursor: zoom-in; }\n\n.mfp-auto-cursor .mfp-content {\n  cursor: auto; }\n\n.mfp-close,\n.mfp-arrow,\n.mfp-preloader,\n.mfp-counter {\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none; }\n\n.mfp-loading.mfp-figure {\n  display: none; }\n\n.mfp-hide {\n  display: none !important; }\n\n.mfp-preloader {\n  color: #CCC;\n  position: absolute;\n  top: 50%;\n  width: auto;\n  text-align: center;\n  margin-top: -0.8em;\n  left: 8px;\n  right: 8px;\n  z-index: 1044; }\n  .mfp-preloader a {\n    color: #CCC; }\n    .mfp-preloader a:hover {\n      color: #FFF; }\n\n.mfp-s-ready .mfp-preloader {\n  display: none; }\n\n.mfp-s-error .mfp-content {\n  display: none; }\n\nbutton.mfp-close,\nbutton.mfp-arrow {\n  overflow: visible;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n  display: block;\n  outline: none;\n  padding: 0;\n  z-index: 1046;\n  box-shadow: none;\n  touch-action: manipulation; }\n\nbutton::-moz-focus-inner {\n  padding: 0;\n  border: 0; }\n\n.mfp-close {\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  position: absolute;\n  right: 0;\n  top: 0;\n  text-decoration: none;\n  text-align: center;\n  opacity: 0.65;\n  padding: 0 0 18px 10px;\n  color: #FFF;\n  font-style: normal;\n  font-size: 28px;\n  font-family: Arial, Baskerville, monospace; }\n  .mfp-close:hover,\n  .mfp-close:focus {\n    opacity: 1; }\n  .mfp-close:active {\n    top: 1px; }\n\n.mfp-close-btn-in .mfp-close {\n  color: #333; }\n\n.mfp-image-holder .mfp-close,\n.mfp-iframe-holder .mfp-close {\n  color: #FFF;\n  right: -6px;\n  text-align: right;\n  padding-right: 6px;\n  width: 100%; }\n\n.mfp-counter {\n  position: absolute;\n  top: 0;\n  right: 0;\n  color: #CCC;\n  font-size: 12px;\n  line-height: 18px;\n  white-space: nowrap; }\n\n.mfp-arrow {\n  position: absolute;\n  opacity: 0.65;\n  margin: 0;\n  top: 50%;\n  margin-top: -55px;\n  padding: 0;\n  width: 90px;\n  height: 110px;\n  -webkit-tap-highlight-color: transparent; }\n  .mfp-arrow:active {\n    margin-top: -54px; }\n  .mfp-arrow:hover,\n  .mfp-arrow:focus {\n    opacity: 1; }\n  .mfp-arrow:before,\n  .mfp-arrow:after {\n    content: '';\n    display: block;\n    width: 0;\n    height: 0;\n    position: absolute;\n    left: 0;\n    top: 0;\n    margin-top: 35px;\n    margin-left: 35px;\n    border: medium inset transparent; }\n  .mfp-arrow:after {\n    border-top-width: 13px;\n    border-bottom-width: 13px;\n    top: 8px; }\n  .mfp-arrow:before {\n    border-top-width: 21px;\n    border-bottom-width: 21px;\n    opacity: 0.7; }\n\n.mfp-arrow-left {\n  left: 0; }\n  .mfp-arrow-left:after {\n    border-right: 17px solid #FFF;\n    margin-left: 31px; }\n  .mfp-arrow-left:before {\n    margin-left: 25px;\n    border-right: 27px solid #3F3F3F; }\n\n.mfp-arrow-right {\n  right: 0; }\n  .mfp-arrow-right:after {\n    border-left: 17px solid #FFF;\n    margin-left: 39px; }\n  .mfp-arrow-right:before {\n    border-left: 27px solid #3F3F3F; }\n\n.mfp-iframe-holder {\n  padding-top: 40px;\n  padding-bottom: 40px; }\n  .mfp-iframe-holder .mfp-content {\n    line-height: 0;\n    width: 100%;\n    max-width: 900px; }\n  .mfp-iframe-holder .mfp-close {\n    top: -40px; }\n\n.mfp-iframe-scaler {\n  width: 100%;\n  height: 0;\n  overflow: hidden;\n  padding-top: 56.25%; }\n  .mfp-iframe-scaler iframe {\n    position: absolute;\n    display: block;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);\n    background: #000; }\n\n/* Main image in popup */\nimg.mfp-img {\n  width: auto;\n  max-width: 100%;\n  height: auto;\n  display: block;\n  line-height: 0;\n  box-sizing: border-box;\n  padding: 40px 0 40px;\n  margin: 0 auto; }\n\n/* The shadow behind the image */\n.mfp-figure {\n  line-height: 0; }\n  .mfp-figure:after {\n    content: '';\n    position: absolute;\n    left: 0;\n    top: 40px;\n    bottom: 40px;\n    display: block;\n    right: 0;\n    width: auto;\n    height: auto;\n    z-index: -1;\n    box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);\n    background: #444; }\n  .mfp-figure small {\n    color: #BDBDBD;\n    display: block;\n    font-size: 12px;\n    line-height: 14px; }\n  .mfp-figure figure {\n    margin: 0; }\n\n.mfp-bottom-bar {\n  margin-top: -36px;\n  position: absolute;\n  top: 100%;\n  left: 0;\n  width: 100%;\n  cursor: auto; }\n\n.mfp-title {\n  text-align: left;\n  line-height: 18px;\n  color: #F3F3F3;\n  word-wrap: break-word;\n  padding-right: 36px; }\n\n.mfp-image-holder .mfp-content {\n  max-width: 100%; }\n\n.mfp-gallery .mfp-image-holder .mfp-figure {\n  cursor: pointer; }\n\n@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {\n  /**\n       * Remove all paddings around the image on small screen\n       */\n  .mfp-img-mobile .mfp-image-holder {\n    padding-left: 0;\n    padding-right: 0; }\n  .mfp-img-mobile img.mfp-img {\n    padding: 0; }\n  .mfp-img-mobile .mfp-figure:after {\n    top: 0;\n    bottom: 0; }\n  .mfp-img-mobile .mfp-figure small {\n    display: inline;\n    margin-left: 5px; }\n  .mfp-img-mobile .mfp-bottom-bar {\n    background: rgba(0, 0, 0, 0.6);\n    bottom: 0;\n    margin: 0;\n    top: auto;\n    padding: 3px 5px;\n    position: fixed;\n    box-sizing: border-box; }\n    .mfp-img-mobile .mfp-bottom-bar:empty {\n      padding: 0; }\n  .mfp-img-mobile .mfp-counter {\n    right: 5px;\n    top: 3px; }\n  .mfp-img-mobile .mfp-close {\n    top: 0;\n    right: 0;\n    width: 35px;\n    height: 35px;\n    line-height: 35px;\n    background: rgba(0, 0, 0, 0.6);\n    position: fixed;\n    text-align: center;\n    padding: 0; } }\n\n@media all and (max-width: 900px) {\n  .mfp-arrow {\n    -webkit-transform: scale(0.75);\n    transform: scale(0.75); }\n  .mfp-arrow-left {\n    -webkit-transform-origin: 0;\n    transform-origin: 0; }\n  .mfp-arrow-right {\n    -webkit-transform-origin: 100%;\n    transform-origin: 100%; }\n  .mfp-container {\n    padding-left: 6px;\n    padding-right: 6px; } }\n"
  },
  {
    "path": "docs/assets/css/owl.carousel.css",
    "content": "/* \r\n * \tCore Owl Carousel CSS File\r\n *\tv1.3.3\r\n */\r\n\r\n/* clearfix */\r\n.owl-carousel .owl-wrapper:after {\r\n\tcontent: \".\";\r\n\tdisplay: block;\r\n\tclear: both;\r\n\tvisibility: hidden;\r\n\tline-height: 0;\r\n\theight: 0;\r\n}\r\n/* display none until init */\r\n.owl-carousel{\r\n\tdisplay: none;\r\n\tposition: relative;\r\n\twidth: 100%;\r\n\t-ms-touch-action: pan-y;\r\n}\r\n.owl-carousel .owl-wrapper{\r\n\tdisplay: none;\r\n\tposition: relative;\r\n\t-webkit-transform: translate3d(0px, 0px, 0px);\r\n}\r\n.owl-carousel .owl-wrapper-outer{\r\n\toverflow: hidden;\r\n\tposition: relative;\r\n\twidth: 100%;\r\n}\r\n.owl-carousel .owl-wrapper-outer.autoHeight{\r\n\t-webkit-transition: height 500ms ease-in-out;\r\n\t-moz-transition: height 500ms ease-in-out;\r\n\t-ms-transition: height 500ms ease-in-out;\r\n\t-o-transition: height 500ms ease-in-out;\r\n\ttransition: height 500ms ease-in-out;\r\n}\r\n\t\r\n.owl-carousel .owl-item{\r\n\tfloat: left;\r\n}\r\n.owl-controls .owl-page,\r\n.owl-controls .owl-buttons div{\r\n\tcursor: pointer;\r\n}\r\n.owl-controls {\r\n\t-webkit-user-select: none;\r\n\t-khtml-user-select: none;\r\n\t-moz-user-select: none;\r\n\t-ms-user-select: none;\r\n\tuser-select: none;\r\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\r\n}\r\n\r\n/* mouse grab icon */\r\n.grabbing { \r\n    cursor:url(grabbing.png) 8 8, move;\r\n}\r\n\r\n/* fix */\r\n.owl-carousel  .owl-wrapper,\r\n.owl-carousel  .owl-item{\r\n\t-webkit-backface-visibility: hidden;\r\n\t-moz-backface-visibility:    hidden;\r\n\t-ms-backface-visibility:     hidden;\r\n  -webkit-transform: translate3d(0,0,0);\r\n  -moz-transform: translate3d(0,0,0);\r\n  -ms-transform: translate3d(0,0,0);\r\n}\r\n\r\n"
  },
  {
    "path": "docs/assets/css/owl.theme.css",
    "content": "/*\r\n* \tOwl Carousel Owl Demo Theme \r\n*\tv1.3.3\r\n*/\r\n\r\n.owl-theme .owl-controls{\r\n\tmargin-top: 10px;\r\n\ttext-align: center;\r\n}\r\n\r\n/* Styling Next and Prev buttons */\r\n\r\n.owl-theme .owl-controls .owl-buttons div{\r\n\tcolor: #FFF;\r\n\tdisplay: inline-block;\r\n\tzoom: 1;\r\n\t*display: inline;/*IE7 life-saver */\r\n\tmargin: 5px;\r\n\tpadding: 3px 10px;\r\n\tfont-size: 12px;\r\n\t-webkit-border-radius: 30px;\r\n\t-moz-border-radius: 30px;\r\n\tborder-radius: 30px;\r\n\tbackground: #869791;\r\n\tfilter: Alpha(Opacity=50);/*IE7 fix*/\r\n\topacity: 0.5;\r\n}\r\n/* Clickable class fix problem with hover on touch devices */\r\n/* Use it for non-touch hover action */\r\n.owl-theme .owl-controls.clickable .owl-buttons div:hover{\r\n\tfilter: Alpha(Opacity=100);/*IE7 fix*/\r\n\topacity: 1;\r\n\ttext-decoration: none;\r\n}\r\n\r\n/* Styling Pagination*/\r\n\r\n.owl-theme .owl-controls .owl-page{\r\n\tdisplay: inline-block;\r\n\tzoom: 1;\r\n\t*display: inline;/*IE7 life-saver */\r\n}\r\n.owl-theme .owl-controls .owl-page span{\r\n\tdisplay: block;\r\n\twidth: 12px;\r\n\theight: 12px;\r\n\tmargin: 5px 7px;\r\n\tfilter: Alpha(Opacity=50);/*IE7 fix*/\r\n\topacity: 0.5;\r\n\t-webkit-border-radius: 20px;\r\n\t-moz-border-radius: 20px;\r\n\tborder-radius: 20px;\r\n\tbackground: #869791;\r\n}\r\n\r\n.owl-theme .owl-controls .owl-page.active span,\r\n.owl-theme .owl-controls.clickable .owl-page:hover span{\r\n\tfilter: Alpha(Opacity=100);/*IE7 fix*/\r\n\topacity: 1;\r\n}\r\n\r\n/* If PaginationNumbers is true */\r\n\r\n.owl-theme .owl-controls .owl-page span.owl-numbers{\r\n\theight: auto;\r\n\twidth: auto;\r\n\tcolor: #FFF;\r\n\tpadding: 2px 10px;\r\n\tfont-size: 12px;\r\n\t-webkit-border-radius: 30px;\r\n\t-moz-border-radius: 30px;\r\n\tborder-radius: 30px;\r\n}\r\n\r\n/* preloading images */\r\n.owl-item.loading{\r\n\tmin-height: 150px;\r\n\tbackground: url(AjaxLoader.gif) no-repeat center center\r\n}"
  },
  {
    "path": "docs/assets/css/style.css",
    "content": "\r\n/*----- 1. Reset.css -----*/\r\n\r\n/* http://meyerweb.com/eric/tools/css/reset/\r\n   v2.0 | 20110126\r\n   License: none (public domain)\r\n*/\r\n\r\nhtml, body, div, span, applet, object, iframe,\r\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\r\na, abbr, acronym, address, big, cite, code,\r\ndel, dfn, em, img, ins, kbd, q, s, samp,\r\nsmall, strike, strong, sub, sup, tt, var,\r\nb, u, i, center,\r\ndl, dt, dd, ol, ul, li,\r\nfieldset, form, label, legend,\r\ntable, caption, tbody, tfoot, thead, tr, th, td,\r\narticle, aside, canvas, details, embed,\r\nfigure, figcaption, footer, header, hgroup,\r\nmenu, nav, output, ruby, section, summary,\r\ntime, mark, audio, video {\r\n\tmargin: 0;\r\n\tpadding: 0;\r\n\tborder: 0;\r\n\tfont-size: 100%;\r\n\tfont: inherit;\r\n\tvertical-align: baseline;\r\n}\r\n/* HTML5 display-role reset for older browsers */\r\narticle, aside, details, figcaption, figure,\r\nfooter, header, hgroup, menu, nav, section {\r\n\tdisplay: block;\r\n}\r\nbody {\r\n\tline-height: 1;\r\n}\r\nol, ul {\r\n\tlist-style: none;\r\n}\r\nblockquote, q {\r\n\tquotes: none;\r\n}\r\nblockquote:before, blockquote:after,\r\nq:before, q:after {\r\n\tcontent: '';\r\n\tcontent: none;\r\n}\r\ntable {\r\n\tborder-collapse: collapse;\r\n\tborder-spacing: 0;\r\n}\r\n\r\n\r\n/* --- Common Styles ---*/\r\n\r\nbody {\r\n\r\n\tfont-family: 'Open Sans';\r\n}\r\n\r\nh1, h2, h3, h4, h5, h6 {\r\n\tfont-family: 'Open Sans';\r\n  font-size: 16px;\r\n}\r\n\r\np {\r\n\tfont-family: 'Open Sans';\r\n\tfont-size: 14px;\r\n}\r\n\r\n/*----- Helper Classes -----*/\r\n\r\nhtml * {\r\n\ttext-rendering: optimizeLegibility !important;\r\n  -webkit-font-smoothing: antialiased;\r\n  -moz-osx-font-smoothing: grayscale;\r\n}\r\n\r\nbody {\r\n\t-webkit-font-smoothing: antialiased;\r\n\t-moz-osx-font-smoothing: grayscale;\r\n}\r\n\r\n*, *:after, *:before {\r\n  -webkit-box-sizing: border-box;\r\n  -moz-box-sizing: border-box;\r\n  box-sizing: border-box;\r\n}\r\n\r\n::-moz-selection {\r\n    color: #FFFFFF;\r\n    background: #23D3D3;\r\n}\r\n\r\n::selection {\r\n    color: #FFFFFF;\r\n    background: #23D3D3;\r\n}\r\n\r\n.nopadding {\r\n\tpadding: 0;\r\n}\r\n\r\n.custom-padding {\r\n\tpadding-left: 10px;\r\n\tpadding-right: 10px;\r\n}\r\n\r\n.container-m {\r\n\tmax-width: 1024px;\r\n\tmargin: 0 auto !important;\r\n\tpadding-left: 40px;\r\n\tpadding-right: 40px;\r\n\tposition: relative;\r\n}\r\n\r\n.container-s {\r\n\tmax-width: 920px;\r\n\tmargin: 0 auto !important;\r\n\tpadding-left: 40px;\r\n\tpadding-right: 40px;\r\n\tposition: relative;\r\n}\r\n\r\n#loading {\r\n   width: 100%;\r\n   height: 100%;\r\n   top: 0px;\r\n   left: 0px;\r\n   position: fixed;\r\n   opacity: 1;\r\n   background-color: #F2F2F2;\r\n   z-index: 9999;\r\n   text-align: center;\r\n}\r\n\r\n#loading-image {\r\n\tdisplay: inline;\r\n  top: 40%;\r\n  position: relative;\r\n  z-index: 9999;\r\n}\r\n\r\n\r\n.logo {\r\n\tposition: fixed;\r\n\ttop: 5%;\r\n\tleft: 2%;\r\n\tz-index: 11;\r\n}\r\n\r\n.logo .tld {\r\n\tbackground: #047aed;\r\n}\r\n\r\n.tld {\r\n\twidth: 40px;\r\n\theight: 40px;\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n\tborder-radius: 50%;\r\n\tdisplay: table;\r\n}\r\n\r\n.tld-text {\r\n\tdisplay: table-cell;\r\n  vertical-align: middle;\r\n  text-align: center;\r\n}\r\n\r\n.tld-text a {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 14px;\r\n\tfont-weight: 600;\r\n\tcolor: #FFFFFF !important;\r\n\ttext-decoration: none !important;\r\n}\r\n\r\n.tld-text a::after {\r\n\tdisplay: none;\r\n}\r\n\r\n\r\n/*------ Navbar Styling ------*/\r\n\r\n.navbar {\r\n  font-family: \"Montserrat\";\r\n\tpadding: 15px 0;\r\n\t/*height: 80px;*/\r\n\tbackground-color: #FFFFFF !important;\r\n\tborder-bottom: 1px solid #EFEFF1;\r\n\t-webkit-transition: 0.5s all ease;\r\n\ttransition: 0.5s all ease;\r\n}\r\n\r\n.wt-border {\r\n\tborder-bottom: 2px solid #FFFFFF !important;\r\n}\r\n\r\n.no-border {\r\n\tborder: none !important;\r\n}\r\n\r\n.navbar .navbar-brand {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 18px;\r\n\tfont-weight: 600;\r\n\tletter-spacing: 0px;\r\n\tcolor: #333347 !important;\r\n\tvertical-align: middle;\r\n}\r\n\r\n.navbar .navbar-brand img {\r\n\tvertical-align: middle;\r\n\tmargin-right: 0.3em;\r\n}\r\n\r\n.navbar .navbar-toggler {\r\n\tborder: none;\r\n}\r\n\r\n.navbar span.navbar-toggler-icon {\r\n\tbackground-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0,0,0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E\");\r\n}\r\n\r\n.navbar span.navbar-toggler-icon::before {\r\n\toutline: none;\r\n}\r\n\r\n.navbar .navbar-toggler:focus {\r\n\toutline: none;\r\n}\r\n\r\n.navbar-nav {\r\n\theight: auto;\r\n\tbackground: #FFFFFF;\r\n\tpadding: 0 1.5rem;\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n\t-webkit-transition: 0.5s all ease; /* For Safari 3.1 to 6.0 */\r\n\ttransition: 0.5s all ease;\r\n}\r\n\r\n.navbar-nav .nav-item {\r\n\tmargin-right: 0;\r\n\tmargin-top: 1.5rem;\r\n\tfont-size: 0.85rem;\r\n\tfont-weight: 400;\r\n  text-transform: capitalize;\r\n  color: #333347;\r\n\tdisplay: flex;\r\n}\r\n\r\n.navbar-nav .nav-item .nav-link {\r\n  color: #333347;\r\n\tfont-weight: 500;\r\n\tdisplay: flex;\r\n\tvertical-align: middle;\r\n}\r\n\r\n.navbar-nav .nav-item .nav-link:hover {\r\n  color: #333347;\r\n\t-webkit-transition: 0.5s;\r\n\ttransition: 0.5s;\r\n}\r\n\r\n.navbar-nav .nav-item .nav-link:focus {\r\n  color: #333347;\r\n}\r\n\r\n.btn-nav {\r\n\tdisplay: inline-block;\r\n\theight: 38px;\r\n\tpadding: 0 30px;\r\n\ttext-align: center;\r\n\tfont-size: 12px;\r\n\tfont-weight: 600;\r\n\tline-height: 36px;\r\n\tletter-spacing: 1px;\r\n\tmargin: 25px 0;\r\n\ttext-transform: uppercase;\r\n\ttext-decoration: none !important;\r\n\twhite-space: nowrap;\r\n\tcursor: pointer;\r\n\tbackground-color: transparent;\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n\tborder: 1px solid #047aed !important;\r\n\tborder-radius: 50px;\r\n\tbox-sizing: border-box;\r\n\t-webkit-transition: 0.2s;\r\n\t-moz-transition: 0.2s;\r\n\ttransition: 0.2s;\r\n}\r\n\r\n.btn-nav:hover {\r\n\tcolor: #FFFFFF;\r\n\tbackground: #047aed;\r\n}\r\n\r\n.btn-nav:focus, .btn-nav:active {\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n}\r\n\r\n/*---- Navbar Alt -----*/\r\n\r\n.navbar-alt {\r\n\tbackground: transparent !important;\r\n}\r\n\r\n.navbar-alt .navbar-nav {\r\n\tbackground: transparent !important;\r\n}\r\n/*\r\n.navbar-alt .btn-nav {\r\n\tbackground: #563d7c !important;\r\n\tborder-color: #563d7c !important;\r\n}*/\r\n\r\n.navbar-alt .nav-item .nav-link {\r\n  color: #FFFFFF;\r\n}\r\n\r\n.navbar-alt .nav-item .nav-link:hover, .navbar-alt .nav-item .nav-link:focus {\r\n  color: rgba(255, 255, 255, 0.7);\r\n}\r\n\r\n.navbar-alt .navbar-brand {\r\n\tcolor: #FFFFFF !important;\r\n}\r\n\r\n\r\n@media only screen and (max-width: 767px) {\r\n\r\n\t.navbar {\r\n\t\tpadding: 15px;\r\n\t}\r\n\r\n\t.navbar .navbar-nav {\r\n\t\tbackground: #FFFFFF !important;\r\n\t\tpadding-bottom: 25px;\r\n\t}\r\n\r\n .navbar-nav .nav-item {\r\n\t\tdisplay: block;\r\n\t}\r\n\r\n\t.nav-white .nav-item .nav-link {\r\n\t\tcolor: #4957B8;\r\n\t}\r\n\r\n\t.navbar-alt .nav-item .nav-link {\r\n\t  color: #333347;\r\n\t}\r\n\r\n\t.navbar .btn-cta {\r\n\t\tpadding: 0 30px;\r\n\t}\r\n\r\n}\r\n\r\n@media only screen and (min-width: 240px) {\r\n\r\n.navbar.past-main {\r\n\tbackground: #FFFFFF !important;\r\n\tborder-bottom: 1px solid #EFEFF1;\r\n}\r\n\r\n.navbar.effect-main {\r\n  -webkit-transition: all 0.3s;\r\n  transition: all 0.3s;\r\n}\r\n\r\n.navbar.past-main .navbar-brand {\r\n\tcolor: #333347 !important;\r\n}\r\n\r\n.nav-white.past-main .nav-item .nav-link {\r\n  color: #333347;\r\n\tfont-weight:500;\r\n}\r\n\r\n.navbar.past-main .nav-item .nav-link {\r\n\tcolor: #333347;\r\n\tfont-weight: 500;\r\n}\r\n\r\n.navbar.past-main .nav-item:hover .nav-link {\r\n\tcolor: #23D3D3;\r\n}\r\n\r\n.navbar.past-main .navbar-brand {\r\n\tcolor: #333347;\r\n}\r\n/*\r\n.navbar.past-main span.navbar-toggler-icon {\r\n\tbackground-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.6)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E\");\r\n}*/\r\n\r\n.nav-white.effect-main {\r\n  -webkit-transition: all 0.3s;\r\n  transition: all 0.3s;\r\n}\r\n\r\n}\r\n\r\n/*----------------- Hero Section Styling ------------------*/\r\n\r\n.main {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n}\r\n\r\n.payment{\r\n  padding: 30px 0 75px 0;\r\n}\r\n\r\n.what {\r\n  padding: 75px 0 75px 0;\r\n}\r\n\r\n.first {\r\n  padding: 110px 0 75px 0 !important;\r\n\tbackground: #F7F7F8;\r\n}\r\n\r\n.home {\r\n  padding: 75px 0 75px 0;\r\n\tbackground: #F7F7F8;\r\n}\r\n\r\n.home .hero-content {\r\n\tpadding: 25px 0 0 0;\r\n}\r\n\r\n.centered {\r\n\tfloat: none !important;\r\n  margin-left: auto !important;\r\n  margin-right: auto !important;\r\n}\r\n\r\n.home h1 {\r\n\tfont-size: 42px;\r\n\tfont-weight: 300;\r\n\tcolor: #FFFFFF;\r\n\tcolor: #252525;\r\n\tline-height: 1.2;\r\n\tletter-spacing: -0.01em;\r\n}\r\n\r\n.home .hero-content-inner p {\r\n\tfont-size: 18px;\r\n\tfont-weight: 400;\r\n\tcolor: rgb(129, 129, 152);\r\n\tmax-width: 630px;\r\n\tmargin: 0 auto;\r\n\tletter-spacing: 0;\r\n\tline-height: 1.6;\r\n\tmargin-top: 10px;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.btn-success {\r\n\tfont-family: 'Montserrat';\r\n\tdisplay: inline-block;\r\n  height: 42px;\r\n  padding: 0 15px;\r\n  text-align: center;\r\n  font-size: 12px;\r\n  font-weight: 600;\r\n  line-height: 40px;\r\n  letter-spacing: 1px;\r\n\tmargin: 25px 0;\r\n  text-transform: uppercase;\r\n\ttext-decoration: none !important;\r\n  white-space: nowrap;\r\n  cursor: pointer;\r\n\tbackground-color: transparent;\r\n\tbackground: #28a745;\r\n  color: #FFFFFF;\r\n  border: 1px solid #28a745 !important;\r\n  border-radius: 20px;\r\n  box-sizing: border-box;\r\n\t-webkit-transition: 0.2s;\r\n\t-moz-transition: 0.2s;\r\n\ttransition: 0.2s;\r\n}\r\n\r\n.btn-success:hover {\r\n\tcolor: #FFFFFF;\r\n\tbackground: #28a745;\r\n\tborder: 1px solid #28a745 !important;\r\n\toutline: none !important;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.btn-success:focus, .btn-success:active {\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n\tborder: 1px solid transparent !important;\r\n\toutline: none !important;\r\n}\r\n\r\n.btn-action {\r\n\tfont-family: 'Montserrat';\r\n\tdisplay: inline-block;\r\n  height: 42px;\r\n  padding: 0 15px;\r\n  text-align: center;\r\n  font-size: 12px;\r\n  font-weight: 600;\r\n  line-height: 40px;\r\n  letter-spacing: 1px;\r\n\tmargin: 25px 0;\r\n  text-transform: uppercase;\r\n\ttext-decoration: none !important;\r\n  white-space: nowrap;\r\n  cursor: pointer;\r\n\tbackground-color: transparent;\r\n\tbackground: #047aed;\r\n  color: #FFFFFF;\r\n  border: 1px solid #047aed !important;\r\n  border-radius: 20px;\r\n  box-sizing: border-box;\r\n\t-webkit-transition: 0.2s;\r\n\t-moz-transition: 0.2s;\r\n\ttransition: 0.2s;\r\n}\r\n\r\n.btn-action:hover {\r\n\tcolor: #FFFFFF;\r\n\tbackground: #047aed;\r\n\tborder: 1px solid #047aed !important;\r\n\toutline: none !important;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.btn-action:focus, .btn-action:active {\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n\tborder: 1px solid transparent !important;\r\n\toutline: none !important;\r\n}\r\n\r\n.btn-alt {\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n}\r\n\r\n.btn-alt:hover {\r\n\tbackground: #047aed;\r\n\tcolor: #FFFFFF;\r\n\tborder: 1px solid #6d48e5 !important;\r\n\toutline: none !important;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.btn-white {\r\n\tbackground: #FFFFFF;\r\n\tcolor: #047aed;\r\n}\r\n\r\n.btn-white:hover {\r\n\tbackground: #FFFFFF;\r\n\tcolor: #047aed;\r\n\tborder: 1px solid #FFFFFF !important;\r\n\toutline: none !important;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.home .client-list {\r\n\tmargin-top: 25px;\r\n}\r\n\r\n.home .client-list ul {\r\n\tlist-style-type: none;\r\n\ttext-align: center;\r\n}\r\n\r\n.home .client-list ul li {\r\n  display: inline;\r\n\tmargin: 0 20px;\r\n}\r\n\r\n.home .client-list ul li img {\r\n  width: 100px;\r\n\topacity: 0.6;\r\n\tcursor: pointer;\r\n}\r\n\r\n.home .client-list ul li img:hover {\r\n\topacity: 0.9;\r\n}\r\n\r\n\r\n/*------ Home 2 Styling ------*/\r\n\r\n.home-2 {\r\n\tbackground: #FFEEFF;\r\n\tbackground: #fafafa;\r\n\tbackground: linear-gradient(to bottom, #0ab3e4, #102976);\r\n\tbackground: #047aed;\r\n\tposition: relative;\r\n\tpadding: 100px 0 50px 0;\r\n}\r\n\r\n.home-2::before, .home-2::after {\r\n  content: ' ';\r\n  position: absolute;\r\n  height: 120px;\r\n  bottom: -60px;\r\n  left: 0;\r\n  right: 0;\r\n  background: #FFFFFF;\r\n  transform: skewY(-5deg);\r\n  -webkit-transform: skewY(-5deg);\r\n  -moz-transform: skewY(-3deg);\r\n  -ms-transform: skewY(-3deg);\r\n  -o-transform: skewY(-3deg);\r\n\t}\r\n\r\n.home-2 .hero-img img {\r\n  width: 100%;\r\n  margin-top: 20px;\r\n}\r\n\r\n.home-2 .hero-content {\r\n\tdisplay: flex;\r\n\theight: 100%;\r\n\tpadding: 0 !important;\r\n}\r\n\r\n.home-2 .hero-content .hero-content-inner {\r\n\tmargin: auto;\r\n\ttext-align: center;\r\n}\r\n\r\n.home-2 h1 {\r\n\tfont-size: 42px;\r\n\tfont-weight: 300;\r\n\tcolor: #FFFFFF;\r\n\tline-height: 1.2;\r\n\tletter-spacing: -0.01em;\r\n}\r\n\r\n.home-2 p {\r\n\tfont-size: 18px;\r\n\tfont-weight: 400;\r\n\tcolor: rgba(255, 255, 255, 0.7);\r\n\tmax-width: none;\r\n\tletter-spacing: 0;\r\n\tline-height: 1.6;\r\n\tmargin-top: 25px;\r\n\tmargin-bottom: 0;\r\n}\r\n\r\n.home-2 .client-list ul {\r\n\ttext-align: left;\r\n}\r\n\r\n.home-2 .client-list ul li {\r\n\tmargin: 0 20px 0 0;\r\n}\r\n\r\n.home-2 .hero-form {\r\n\tposition: relative;\r\n\tz-index: 1;\r\n}\r\n\r\n.home-2 .hero-form #contactForm {\r\n\tbackground: #FFFFFF;\r\n\tpadding: 35px;\r\n\tborder-radius: 10px;\r\n\tmax-width: 380px !important;\r\n\tmargin: 0 auto;\r\n\tfloat: none;\r\n\tz-index: 1111 !important;\r\n\tbox-shadow: 0 5px 50px rgba(0, 0, 10, 0.2);\r\n}\r\n\r\n.home-2 .hero-form #contactForm label {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 14px;\r\n\tfont-weight: 600;\r\n\tcolor: #1e266d;\r\n\tline-height: 1.4;\r\n\tmargin: 10px 0;\r\n}\r\n\r\n.home-2 .hero-form #contactForm input, .home-2 .hero-form #contactForm textarea {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 14px;\r\n\tfont-weight: 400;\r\n\tcolor: #1e266d;\r\n\tborder: 0;\r\n\tborder-radius: 0;\r\n\tborder-bottom: 2px solid #b4becb;\r\n}\r\n\r\n.home-2 .hero-form #contactForm .btn-action {\r\n\tmargin: 20px 0;\r\n\tmin-width: 100%;\r\n}\r\n\r\n\r\n.help-block {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 12px;\r\n\tfont-weight: 400;\r\n\tmargin-top: 5px;\r\n\tcolor: #FF3333;\r\n\tfont-style: normal !important;\r\n}\r\n\r\n.text-success, .text-danger {\r\n\tfont-size: 14px;\r\n\tfont-family: 'Poppins';\r\n}\r\n\r\n\r\n/*------------- Home 3 Styling --------------*/\r\n\r\n\r\n.home-3 {\r\n\t/*padding: 125px 0 75px 0;*/\r\n}\r\n\r\n.home-3 .hero-content {\r\n\tdisplay: flex;\r\n\theight: 100%;\r\n\tpadding: 0 !important;\r\n}\r\n\r\n.home-3 .hero-content .hero-content-inner {\r\n\tmargin: auto;\r\n\ttext-align: center;\r\n}\r\n\r\n.home-3 .hero-content h4 {\r\n  text-align:left;\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: rgba(0, 0, 0, 0.4);\r\n\tline-height: 1.2;\r\n\ttext-transform: uppercase;\r\n\tletter-spacing: 1px;\r\n\tmargin-bottom: 10px;\r\n  padding-top:15px;\r\n}\r\n\r\n.home-3 .hero-content h1 {\r\n  text-align:left;\r\n\tfont-size: 42px;\r\n\tfont-weight: 300;\r\n\tcolor: rgba(0, 0, 0, 0.7);\r\n\tline-height: 1.2;\r\n}\r\n\r\n.home-3 .hero-content p {\r\n  text-align:left;\r\n\tfont-size: 18px;\r\n\tfont-weight: 400;\r\n\tcolor: rgba(0, 0, 0, 0.5);\r\n\tmax-width: none;\r\n\tletter-spacing: 0;\r\n\tline-height: 1.6;\r\n\tmargin-top: 15px;\r\n\tmargin-bottom: 0;\r\n}\r\n\r\n.home-3 .hero-img img {\r\n    max-width: 100%;\r\n    margin-top: 20px;\r\n    margin-bottom: 50px;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/*------------- Form Styling -----------*/\r\n\r\n.sub-form {\r\n\tposition: relative;\r\n\tmax-width: 420px;\r\n\tmargin: 0 auto;\r\n\tmargin-top: 30px;\r\n}\r\n\r\n.chimp-form .mail {\r\n\tposition: relative;\r\n\tbackground-color: #FFFFFF;\r\n  box-shadow: none;\r\n  -webkit-box-sizing: content-box;\r\n  -moz-box-sizing: content-box;\r\n  box-sizing: content-box;\r\n  transition: all .3s;\r\n}\r\n\r\n.sub-form input {\r\n\tdisplay: block;\r\n\twidth: 100%;\r\n\tmargin: 0 auto;\r\n  color: #6d48e5;\r\n  font-family: 'Montserrat';\r\n  padding: 0;\r\n  font-size: 13px;\r\n\tfont-weight: 500;\r\n\theight: 50px;\r\n  border: 1px solid #047aed;\r\n  border-radius: 4px;\r\n\tbackground-color: #FFFFFF;\r\n  outline: none;\r\n  padding: 0 100px 0 20px;\r\n\tbox-shadow: 0 5px 30px rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.sub-form input:focus {\r\n\toutline: none !important;\r\n\tbackground: #FFFFFF;\r\n\tborder: 1px solid #047aed;\r\n}\r\n\r\n.sub-form .submit-button {\r\n  height: 50px;\r\n\twidth: 100%;\r\n  border: 0;\r\n  border-radius: 4px;\r\n  margin: 0 auto;\r\n\tmargin: 15px 0;\r\n  padding: 0 25px 0 25px;\r\n\tbackground: #047aed;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\ttext-transform: capitalize;\r\n\tletter-spacing: 0;\r\n  color: #FFFFFF;\r\n\tcursor: pointer;\r\n  outline: none;\r\n\tbox-shadow: 0 2px 5px 0 rgba(0, 0, 100,.2);\r\n\t-webkit-transition: 300ms;\r\n\t-moz-transition: 300ms;\r\n\ttransition: 300ms;\r\n}\r\n\r\n.sub-form .submit-button:hover {\r\n\tbox-shadow: 0 5px 25px 0 rgba(0, 0, 100,.2);\r\n}\r\n\r\n.sub-form .submit-button:focus, .sub-form .submit-button:active {\r\n\tbackground: #047aed;\r\n}\r\n\r\n#email-error {\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\tright: 0;\r\n\tbottom: -50%;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 13px;\r\n\tfont-weight: 500;\r\n\tcolor: #FF3333;\r\n}\r\n\r\n#response {\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\tbottom: -45%;\r\n\tvertical-align: middle;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 13px !important;\r\n\tfont-weight: 500;\r\n\tcolor: #15ccbe;\r\n}\r\n\r\n#chimp-email-error {\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\tright: 0;\r\n\tbottom: -45%;\r\n\tvertical-align: middle;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 13px;\r\n\tfont-weight: 500;\r\n\tcolor: red;\r\n}\r\n\r\n.success-message {\r\n\tcolor:#33cc33;\r\n\tmargin-top: 5px;\r\n}\r\n\r\n.form-note p {\r\n\tfont-size: 12px;\r\n\tfont-weight: 500;\r\n\tcolor: #97a6b5\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/*---------- Split Coming Soon Demo Styling -----------*/\r\n\r\n\r\n.home-split {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n}\r\n\r\n.home-split .yd_flx2 {\r\n\tdisplay: -webkit-box;\r\n  display: -moz-box;\r\n  display: -ms-flexbox;\r\n  display: -webkit-flex;\r\n  display: flex;\r\n  -webkit-flex-flow: row wrap;\r\n  justify-content: space-around;\r\n\tline-height: 0;\r\n\tmin-height: 100vh;\r\n}\r\n\r\n.home-split .yd_flx2 > * {\r\n  flex: 1 100%;\r\n}\r\n\r\n.home-split .flx_1 {\r\n\tbackground: #1E3B70;\r\n\tbackground: #dbd9cd;\r\n\tbackground: #047aed;\r\n\tbackground: #6892d5;\r\n\tbackground: #F9F9F9;\r\n\tline-height: normal;\r\n\torder: 2;\r\n\tmin-height: 600px;\r\n\ttext-align: center;\r\n}\r\n\r\n.home-split .flx_2 {\r\n\tbackground: #79d1c3;\r\n\tbackground: url(../images/hg.jpg) no-repeat center center;\r\n\tbackground-size: cover;\r\n\tmin-height: 600px;\r\n\torder: 1;\r\n  padding: 0 !important;\r\n\tmargin: 0 !important\r\n}\r\n\r\n.home-split .flx_1 .section-txt {\r\n\tdisplay: flex;\r\n\tmax-width: 600px;\r\n\tmargin: auto;\r\n\theight: 100%;\r\n}\r\n\r\n.home-split .flx_1 .section-txt .section-txt-inner {\r\n\tmargin: auto; /* Important */\r\n}\r\n\r\n.home-split .flx_1 .section-txt {\r\n\tpadding: 50px 50px;\r\n}\r\n\r\n\r\n.home-split .flx_1 h2 {\r\n\tfont-size: 40px;\r\n\tfont-weight: 700;\r\n\tcolor: rgba(0, 0, 0, 0.65);\r\n\tline-height: 1.2;\r\n\tletter-spacing: 0;\r\n\tmargin-bottom: 20px;\r\n}\r\n\r\n.home-split .flx_1 h4 {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: rgb(129, 129, 152);\r\n\tline-height: 1.4;\r\n\tletter-spacing: 2px;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.home-split .flx_1 p {\r\n\tfont-size: 16px;\r\n\tfont-weight: 400;\r\n\tcolor: rgb(129, 129, 152);\r\n\tline-height: 1.6;\r\n\tmax-width: 360px;\r\n\tmargin: 0 auto;\r\n}\r\n\r\n.home-split .flx_1 a {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 12px;\r\n\tfont-weight: 500;\r\n\tcolor: #23a393;\r\n\tposition: relative;\r\n\tdisplay: inline-block;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.home-split .flx_2 h2 {\r\n\tfont-size: 24px;\r\n\tfont-weight: 700;\r\n\tcolor: rgba(255, 255, 255, 0.95);\r\n\tline-height: 1.2;\r\n\tletter-spacing: 0;\r\n\tmargin-bottom: 20px;\r\n}\r\n\r\n.home-split .btm_block {\r\n\tposition: relative;\r\n\twidth: 100%;\r\n\theight: auto;\r\n}\r\n\r\n.home-split .block_inner {\r\n\tposition: absolute;\r\n\tbottom: 0;\r\n\tleft: 50px;\r\n}\r\n\r\n.home-split .block_txt {\r\n\tmargin: 0 auto;\r\n}\r\n\r\n.home-split .block_txt p {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: #8f2c34;\r\n}\r\n\r\n\r\n\r\n@media only screen and (min-width: 767px) {\r\n\r\n\r\n\t.home-split .flx_1 {\r\n\t\tflex: 1.1 0 0;\r\n\t\torder: 1;\r\n\t\tflex-basis: 50%;\r\n\t\ttransition: 0.3s ease-in;\r\n\t}\r\n\r\n\t.home-split .flx_2 {\r\n\t\tflex: 1 0 0;\r\n\t\torder: 2;\r\n\t\tflex-basis: 50%;\r\n\t\ttransition: 0.3s ease-out;\r\n\t}\r\n}\r\n\r\n\r\n.split_footer {\r\n\tposition: relative;\r\n\tbottom: 0;\r\n\tleft: 0;\r\n\tright: 0;\r\n\ttop: 0;\r\n}\r\n\r\n.split_footer p {\r\n\tfont-size: 12px !important;\r\n}\r\n\r\n.split_footer ul {\r\n\tlist-style-type: none;\r\n\ttext-align: center;\r\n\tmargin-bottom: 20px;\r\n\tposition: absolute;\r\n\tbottom: 0;\r\n\tleft: 0;\r\n\tright: 0;\r\n}\r\n\r\n\r\n.split_footer ul li {\r\n\tfont-family: \"Montserrat\";\r\n  font-size: 16px;\r\n  font-weight: 500;\r\n\tletter-spacing: 0;\r\n  display: inline-block;\r\n\tmargin-left: 10px;\r\n  margin-right: 10px;\r\n}\r\n\r\n.split_footer ul li a {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tline-height: 24px;\r\n\ttext-transform: uppercase;\r\n  position: relative;\r\n  display: inline-block;\r\n  color: #FFFFFF;\r\n  text-decoration: none;\r\n}\r\n\r\n.split_footer ul li a:hover {\r\n  text-decoration: none;\r\n  color: #97a6b5;\r\n}\r\n\r\n.split_footer ul li {\r\n\tmargin-left: 8px;\r\n  margin-right: 8px;\r\n}\r\n\r\n.split_footer ul li a img {\r\n\twidth: 21px;\r\n\tvertical-align: middle;\r\n}\r\n\r\nul#countdown {\r\n\tlist-style: none;\r\n\tmargin: 20px 0;\r\n\tpadding: 0;\r\n\tdisplay: inline-block;\r\n\ttext-align: center;\r\n}\r\n\r\nul#countdown li {\r\n\tdisplay: inline-block;\r\n}\r\n\r\n@media only screen and (max-width: 767px) {\r\n\r\n\tul#countdown li span {\r\n\t\tfont-size: 34px;\r\n\t}\r\n\r\n\r\n.home-split .btn-alt {\r\n\tdisplay: block;\r\n}\r\n}\r\n\r\n\r\n.prk-center {\r\n\tposition: relative;\r\n\tleft: 0;\r\n\ttop: 0;\r\n\tbottom: 0;\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\toverflow: hidden;\r\n\tz-index: 1;\r\n\tdisplay: table;\r\n}\r\n\r\n.prk-circle-box {\r\n\tdisplay: table-cell;\r\n\tvertical-align: middle;\r\n\ttext-align: center;\r\n}\r\n\r\n.prk-circle {\r\n\tmargin: 0 auto;\r\n\twidth: 270px;\r\n\theight: 270px;\r\n\tborder-radius: 50%;\r\n\tbackground: #6892d5;\r\n\tbox-shadow: 0 3px 50px 0 rgba(255, 94, 58, 0.1);\r\n\tcolor: #e84545;\r\n\ttransition: all 400ms ease-in;\r\n}\r\n\r\n.prk-text {\r\n\tposition: relative;\r\n\tleft: 0;\r\n\ttop: 0;\r\n\tbottom: 0;\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\toverflow: hidden;\r\n\tz-index: 1;\r\n\tdisplay: table;\r\n}\r\n\r\n.txt-box {\r\n\tdisplay: table-cell;\r\n\tvertical-align: middle;\r\n\ttext-align: center;\r\n}\r\n\r\n\r\n.txt-box ul#countdown li span {\r\n\tfont-family: Arial;\r\n\tfont-size: 24px;\r\n\tfont-weight: 600;\r\n\tline-height: 1;\r\n\tcolor: #FFFFFF;\r\n\tpadding: 6px;\r\n\ttransition: all 400ms ease-in;\r\n}\r\n\r\n.txt-box ul#countdown li.seperator {\r\n\tfont-size: 21px;\r\n\tline-height: 1;\r\n\tvertical-align: top;\r\n\tcolor: #FFFFFF;\r\n\ttransition: all 400ms ease-in;\r\n}\r\n\r\n.txt-box ul#countdown li p {\r\n\tcolor: rgba(255, 255, 255, 0.9);\r\n\tfont-size: 11px;\r\n\tfont-weight: 500;\r\n\tpadding-top: 15px;\r\n\ttransition: all 400ms ease-in;\r\n}\r\n\r\n.txt-box h2 {\r\n\tfont-size: 16px;\r\n\tfont-weight: 400;\r\n\tcolor: rgba(255, 255, 255, 0.8);\r\n\tmargin-bottom: 0.5em;\r\n\ttransition: all 400ms ease-in;\r\n}\r\n\r\n.txt-box h2 span {\r\n\tcolor: #FFFFFF;\r\n\tfont-weight: 700;\r\n}\r\n\r\n.txt-box h3 {\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tcolor: #e84545;\r\n\tmargin-top: 0.5em;\r\n}\r\n\r\n.txt-box a {\r\n\tcolor: #6142d2;\r\n}\r\n\r\n.txt-box a:hover {\r\n\tcolor: #6142d2;\r\n}\r\n\r\n\r\n.chimp-form .mail {\r\n\tposition: relative;\r\n\tbackground-color: #F9F9F9;\r\n  box-shadow: none;\r\n  -webkit-box-sizing: content-box;\r\n  -moz-box-sizing: content-box;\r\n  box-sizing: content-box;\r\n  transition: all .3s;\r\n}\r\n\r\n.form {\r\n\tpadding-top: 25px;\r\n\tposition: relative;\r\n\ttext-align: center;\r\n}\r\n\r\n.form input {\r\n  color: #222222;\r\n  font-family: 'Montserrat';\r\n  padding: 0;\r\n  font-size: 13px;\r\n\tfont-weight: 500;\r\n\theight: 45px;\r\n  border: 0;\r\n  border-radius: 30px;\r\n\tbackground-color: #efefef;\r\n  outline: none;\r\n  padding: 0 100px 0 20px;\r\n\tbox-shadow: 0 5px 30px rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.form input:focus {\r\n\toutline: none !important;\r\n\tborder-color: transparent;\r\n}\r\n\r\n.form .submit-button {\r\n  height: 45px;\r\n  border: 0;\r\n  border-radius: 30px;\r\n  margin-left: -35px;\r\n  padding: 0 25px 0 25px;\r\n\tbackground: #047aed;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\ttext-transform: capitalize;\r\n\tletter-spacing: 0;\r\n  color: #FFFFFF;\r\n\tcursor: pointer;\r\n  outline: none;\r\n\tbox-shadow: 0 5px 30px rgba(255, 255, 255, 0.05);\r\n\t-webkit-transition: 500ms;\r\n\t-moz-transition: 500ms;\r\n\ttransition: 500ms;\r\n}\r\n\r\n#email-error {\r\n\tposition: absolute;\r\n\tleft: 20%;\r\n\tright: 0;\r\n\tbottom: 0%;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 13px;\r\n\tfont-weight: 500;\r\n\tcolor: #FF3333;\r\n}\r\n\r\n#response {\r\n\tposition: absolute;\r\n\tleft: 20%;\r\n\tbottom: -90%;\r\n\tvertical-align: middle;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 13px !important;\r\n\tfont-weight: 500 !important;\r\n\tmargin: 0 !important;\r\n\tcolor: #15ccbe;\r\n}\r\n\r\n#response h4 {\r\n\tfont-size: 13px !important;\r\n\tfont-weight: 500 !important;\r\n\ttext-align: center;\r\n}\r\n\r\n.home-split #chimp-email-error {\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\tbottom: -50%;\r\n\tvertical-align: middle;\r\n\ttext-align: center;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 13px;\r\n\tfont-weight: 500;\r\n\tcolor: #047aed;\r\n}\r\n\r\n.yd_cta_box #chimp-email-error {\r\n\tposition: absolute;\r\n\tleft: 25%;\r\n\tbottom: -50%;\r\n}\r\n\r\n.yd_cta_box #response {\r\n\tposition: absolute;\r\n\tleft: 25%;\r\n\tbottom: -90%;\r\n}\r\n\r\n.success-message {\r\n\tcolor:#047aed;\r\n\tmargin-top: 5px;\r\n}\r\n\r\n.form-note p {\r\n\tfont-size: 12px;\r\n}\r\n\r\n\r\n\r\n/*-----------------------------------------------------------\r\n------------ Service Features Styling Starts ---------------\r\n-----------------------------------------------------------*/\r\n\r\n\r\n.lbl-services {\r\n\tbackground: #FFFFFF;\r\n\tpadding: 50px 0;\r\n\tposition: relative;\r\n}\r\n\r\n.service-intro {\r\n\tpadding: 0 0 50px 0;\r\n}\r\n\r\n.service-intro h1 {\r\n\tfont-size: 32px;\r\n  font-weight: 300;\r\n  color: #364655;\r\n  line-height: 1.2;\r\n\tmargin-bottom: 20px;\r\n}\r\n\r\n.service-intro p {\r\n\tfont-size: 16px;\r\n  font-weight: 400;\r\n  color: rgb(129, 129, 152);\r\n  line-height: 1.6;\r\n\tmax-width: 600px;\r\n\tmargin: 0 auto;\r\n}\r\n\r\n.justify-center {\r\n\tjustify-content: center !important;\r\n\tdisplay: flex;\r\n}\r\n\r\n.lbl_cards {\r\n\twidth: 100%;\r\n\tdisplay: -webkit-box;\r\n\tdisplay: -webkit-flex;\r\n\tdisplay: -ms-flexbox;\r\n\tdisplay: flex;\r\n\t-webkit-flex-wrap: wrap;\r\n\t-ms-flex-wrap: wrap;\r\n\tflex-wrap: wrap;\r\n\tborder-radius: 10px;\r\n\toverflow: hidden;\r\n\ttext-align: center;\r\n}\r\n\r\n/*\r\n.card_single {\r\n\tbackground: #FFFFFF;\r\n\ttext-align: center;\r\n\tpadding: 50px;\r\n\tmargin: 0 0 50px 0;\r\n\tborder-radius: 10px;\r\n\tcursor: pointer;\r\n\t-webkit-transition: 0.3s;\r\n\ttransition: 0.3s;\r\n\tmax-width: 360px;\r\n\tmargin: 0 auto;\r\n\tborder-bottom: 2px solid #e8f1f5;\r\n}*/\r\n\r\n.card_single {\r\n\twidth: 100%;\r\n  margin: 1px;\r\n  /*-webkit-flex-basis: 100%;\r\n  -ms-flex-preferred-size: 100;\r\n  flex-basis: 100%;*/\r\n  min-width: 200px;\r\n  padding: 40px 32px;\r\n  background-color: #FFF;\r\n  -webkit-transition: 0.1s ease-in background-color;\r\n  transition: 0.1s ease-in background-color;\r\n\r\n}\r\n/*\r\n.card_single:hover {\r\n\tbox-shadow: 0 40px 60px 0 rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n.card2 {\r\n\tborder-bottom: 2px solid #fffce6;\r\n}\r\n\r\n.card3 {\r\n\tborder-bottom: 2px solid #ffe9e6;\r\n}*/\r\n\r\n.card-icon {\r\n\twidth: 80px;\r\n\theight: 80px;\r\n\tmargin: 0 auto;\r\n\tborder-radius: 50%;\r\n\tbackground: rgba(30, 166, 154, 0.08);\r\n\tbackground: #edf4f7;\r\n\tdisplay: table;\r\n\ttext-align: center;\r\n}\r\n/*\r\n.card2 .card-icon {\r\n\tbackground: #fffce6;\r\n}\r\n\r\n.card3 .card-icon {\r\n\tbackground: #ffe9e6;\r\n}\r\n*/\r\n\r\n\r\n.card-img {\r\n\tdisplay: table-cell;\r\n\tvertical-align: middle;\r\n  text-align: center;\r\n}\r\n\r\n.card-text {\r\n\tpadding: 15px;\r\n\tmargin-top: 15px;\r\n}\r\n\r\n.card-text h3 {\r\n\tfont-size: 21px;\r\n\tfont-weight: 500;\r\n\tcolor: #364655;\r\n}\r\n\r\n.card-text p {\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tcolor: rgb(129, 129, 152);\r\n\tline-height: 1.6;\r\n\tmargin-top: 15px;\r\n}\r\n\r\n\r\n\r\n\r\n/*-----------------------------------------------------\r\n-------------- Flex Features Section 2 ----------------\r\n-----------------------------------------------------*/\r\n\r\n\r\n/*----------- Flex Features ------------*/\r\n\r\n.flex-split {\r\n\tpadding: 50px 0;\r\n\tbackground: #F7F7F8;\r\n}\r\n\r\n.flex-intro {\r\n\tmargin-bottom: 50px;\r\n\ttext-align: center;\r\n}\r\n\r\n.flex-intro h2 {\r\n\tfont-size: 32px;\r\n\tfont-weight: 300;\r\n\tcolor: #3a3a47;\r\n\tline-height: 1.3;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.flex-intro p {\r\n\tfont-size: 16px;\r\n  font-weight: 500;\r\n  line-height: 1.6;\r\n\tletter-spacing: 0.01em;\r\n  color: #818198;\r\n\tmax-width: 630px;\r\n\tmargin: 0 auto;\r\n\tmargin-top: 15px;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.flex-inner {\r\n\tmargin: 50px 0;\r\n}\r\n\r\n.flex-inner .f-image {\r\n\ttext-align: center;\r\n}\r\n\r\n.flex-inner .f-text {\r\n\tpadding: 0 35px;\r\n\ttext-align: center;\r\n}\r\n\r\n .flex-inner .f-text {\r\n\t-webkit-box-flex:1;\r\n\t-ms-flex:1;\r\n\tflex:1;\r\n\ttext-align: center;\r\n}\r\n\r\n.flex-inner .f-text h2 {\r\n\tfont-size: 24px;\r\n\tfont-weight: 600;\r\n\tcolor: #3a3a47;\r\n\tline-height: 1.3;\r\n\tmargin-top: 25px;\r\n}\r\n\r\n.flex-inner .f-text  p {\r\n\tfont-size: 16px;\r\n  font-weight: 400;\r\n  line-height: 1.6;\r\n\tletter-spacing: 0.01em;\r\n  color: #818198;\r\n\tmargin-top: 15px;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.flex-inner .f-text .left-content a {\r\n\tfont-family: \"Open Sans\";\r\n\tfont-size: 14px;\r\n\tfont-weight: 600;\r\n\tcolor: #047aed;\r\n\tposition: relative;\r\n  display: inline-block;\r\n  text-decoration: none;\r\n}\r\n\r\n.flex-inner .f-text .left-content a::after {\r\n\tcontent: \"\";\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\tbottom: -20%;\r\n\theight: 1px;\r\n\twidth: 50px;\r\n\tbackground: #8798ab;\r\n\t-webkit-transition: 0.3s;\r\n\ttransition: 0.3s;\r\n}\r\n\r\n.flex-inner .f-text .left-content a:hover::after {\r\n\twidth: 75px;\r\n}\r\n\r\n.flex-inner .f-text .left-content a:hover {\r\n\ttext-decoration: none;\r\n}\r\n\r\n.flex-inner.flex-inverted .f-image {\r\n\t-webkit-box-ordinal-group:2;\r\n\t-ms-flex-order:1;\r\n\torder:1\r\n}\r\n\r\n\r\n.flex-inner.flex-inverted .f-image img {\r\n\t-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */\r\n  filter: grayscale(10%);\r\n}\r\n\r\n\r\n/*---------------- YD CTA Box Styling --------------------*/\r\n\r\n\t.yd_cta_box {\r\n\t\tbackground: #FFFFFF;\r\n\t}\r\n\r\n\t.cta_box {\r\n\t\tbackground: #303c42 url(../images/motherboard1.png);\r\n\t\tbackground-repeat: no-repeat;\r\n\t\tbackground-position: right;\r\n\t\tborder-radius: 0;\r\n\t\tdisplay: flex;\r\n\t\tmargin: auto;\r\n\t\theight: 480px;\r\n\t}\r\n\r\n\t.cta_box .cta_box_inner {\r\n\t\tmargin: auto;\r\n\t\tpadding: 0;\r\n\t}\r\n\r\n\t.cta_box .cta_box_inner .box_txt {\r\n\t\tpadding: 0;\r\n\t}\r\n\r\n\t.cta_box .cta_box_inner h4 {\r\n\t\tfont-size: 18px;\r\n\t\tfont-weight: 400;\r\n\t\tline-height: 1.2;\r\n\t\tcolor: rgba(255, 255, 255, 0.8);\r\n\t\tmargin-bottom: 20px;\r\n\t}\r\n\r\n\t.cta_box .cta_box_inner h2 {\r\n\t\tfont-size: 24px;\r\n\t\tfont-weight: 400;\r\n\t\tline-height: 1.6;\r\n\t\tcolor: #FFFFFF;\r\n\t}\r\n/*\r\n\t.cta_box .btn-action {\r\n\t\tbackground: #FFFFFF;\r\n\t\tcolor: #047aed;\r\n\t}*/\r\n\r\n\t.yd_cta_sub {\r\n\t\tpadding: 0;\r\n\t\tbackground: #303c42;\r\n\t\ttext-align: center;\r\n\t}\r\n\r\n\t.cta_sub {\r\n\t\tdisplay: flex;\r\n\t\tmargin: auto;\r\n\t\theight: 480px;\r\n\t}\r\n\r\n\t.cta_sub .cta_sub_inner {\r\n\t\tmargin: auto;\r\n\t\tpadding: 0;\r\n\t}\r\n\r\n\r\n\t.cta_sub .cta_sub_inner h4 {\r\n\t\tfont-size: 14px;\r\n\t\tfont-weight: 400;\r\n\t\tline-height: 1.2;\r\n\t\tletter-spacing: 2px;\r\n\t\ttext-transform: uppercase;\r\n\t\tcolor: rgba(255, 255, 255, 0.8);\r\n\t\tmargin-bottom: 20px;\r\n\t}\r\n\r\n\t.cta_sub .cta_sub_inner h2 {\r\n\t\tfont-size: 24px;\r\n\t\tfont-weight: 300;\r\n\t\tline-height: 1.6;\r\n\t\tcolor: #FFFFFF;\r\n\t}\r\n\r\n\r\n/*------------------ YD Video Ft Section Styling --------------*/\r\n\r\n.yd_boxed .yd_vid_ft {\r\n\tpadding: 70px 0;\r\n}\r\n\r\n.yd_boxed .vid_box {\r\n\tpadding: 50px;\r\n}\r\n\r\n.yd_vid_ft {\r\n\tbackground: #FFFFFF;\r\n\tpadding: 50px 0;\r\n}\r\n\r\n.vid_box {\r\n\tmin-height: 540px;\r\n\twidth: 100%;\r\n\tbackground: rgb(4, 122, 237);\r\n\tbackground: #F7F7F8;\r\n\tborder-radius: 1px;\r\n\tpadding: 100px 50px;\r\n\tposition: relative;\r\n}\r\n/*\r\n.vid_box::before {\r\n  display: block;\r\n  content: \"\";\r\n  width: 100%;\r\n  height: 100%;\r\n  position: absolute;\r\n  left: 0;\r\n  top: 0;\r\n  background: rgba(0, 0, 0, 0.3);\r\n  opacity: 1;\r\n  z-index: 100;\r\n  -webkit-transform: translate3d(0, 0, 0);\r\n  -moz-transform: translate3d(0, 0, 0);\r\n  -ms-transform: translate3d(0, 0, 0);\r\n  -o-transform: translate3d(0, 0, 0);\r\n  transform: translate3d(0, 0, 0);\r\n  -webkit-backface-visibility: hidden;\r\n  -moz-backface-visibility: hidden;\r\n  -ms-backface-visibility: hidden;\r\n  -o-backface-visibility: hidden;\r\n  backface-visibility: hidden;\r\n}*/\r\n\r\n.vid_intro {\r\n\ttext-align: center;\r\n\tmax-width: 580px;\r\n\tmargin: 0 auto;\r\n}\r\n\r\n.vid_intro h2 {\r\n\tfont-size: 34px;\r\n\tfont-weight: 300;\r\n\tcolor: #3a3a47;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.vid_intro p {\r\n\tfont-size: 17px;\r\n\tfont-weight: 500;\r\n\tcolor: rgb(129, 129, 152);\r\n\tline-height: 1.6;\r\n\tmargin-top: 10px;\r\n}\r\n\r\n.yd_vid {\r\n\ttext-align: center;\r\n\tmax-width: 768px;\r\n\tmargin: 0 auto;\r\n\tmargin-top: 75px;\r\n}\r\n\r\n\r\n\r\n/*--------- Left Section Styling -----------*/\r\n\r\n.yd_flx_tr {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\tpadding: 100px 0;\r\n}\r\n\r\n.yd_flx_tr_inner {\r\n\tdisplay: -webkit-box;\r\n  display: -moz-box;\r\n  display: -ms-flexbox;\r\n  display: -webkit-flex;\r\n  display: flex;\r\n  -webkit-flex-flow: row wrap;\r\n  justify-content: space-around;\r\n}\r\n\r\n.yd_flx_tr_inner > * {\r\n  flex: 1 100%;\r\n}\r\n\r\n.left {\r\n\tbackground: #f3f3f5;\r\n\tpadding: 75px;\r\n}\r\n\r\n\r\n.flx_content h2 {\r\n\tfont-size: 24px;\r\n\tfont-weight: 500;\r\n\tcolor: #202124;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.flx_content h4 {\r\n\tfont-size: 18px;\r\n\tfont-weight: 500;\r\n\tcolor: #284184;\r\n\tline-height: 1.4;\r\n\tmargin-top: 40px;\r\n}\r\n\r\n/*--------- Right Section Styling -----------*/\r\n\r\n\r\n.right {\r\n\tbackground-color: #f3f3f5;\r\n\tbackground: #333;\r\n\tline-height: 0;\r\n\tposition: relative;\r\n\tdisplay: -webkit-box;\r\n\tdisplay: -moz-box;\r\n\tdisplay: -ms-flexbox;\r\n\tdisplay: -webkit-flex;\r\n\tdisplay: flex;\r\n\t-webkit-flex-flow: row wrap;\r\n\tjustify-content: space-around;\r\n}\r\n\r\n.right > * {\r\n  flex: 1 100%;\r\n}\r\n\r\n.right .sec-one {\r\n\tbackground-color: #ff524e;\r\n\tbackground-color: #f3f3f5;\r\n}\r\n\r\n.right .sec-two {\r\n\tbackground-color: #FFE16E;\r\n\tbackground-color: #C4FFDD;\r\n\tbackground-color: #ff524e;\r\n\theight: auto;\r\n\tpadding: 50px;\r\n}\r\n\r\n.right .sec-one h2 , .right .sec-two h2 {\r\n\tfont-size: 21px;\r\n\tfont-weight: 600;\r\n\tcolor: #FFF;\r\n\tline-height: 1.2;\r\n}\r\n\r\n\r\n\r\n\r\n/*----------------------------------------\r\n------- Nav Tabs Styling Section ---------\r\n----------------------------------------*/\r\n\r\n\r\n.yd_tabs {\r\n\tpadding: 50px 0;\r\n\tbackground: #f3f3f5;\r\n}\r\n\r\n.yd_tabs .nav-tabs {\r\n  background-color: #f3f3f5;\r\n\tpadding: 25px 0;\r\n\tborder: none !important;\r\n}\r\n\r\n\r\n.yd_tabs .nav-tabs .nav-link {\r\n\toverflow: hidden;\r\n\tborder-radius: 10px;\r\n\tpadding: 25px;\r\n}\r\n\r\n.yd_tabs .nav-tabs .nav-link:hover {\r\n\tborder-color: transparent;\r\n}\r\n\r\n.yd_tabs .nav-tabs .nav-link.active {\r\n  background-color: #f3f3f5;\r\n  color: #433434;\r\n\tborder-color: transparent;\r\n  position: relative;\r\n\tbox-shadow:0 0px 50px rgba(0, 0, 0, .1);\r\n\r\n}\r\n\r\n.yd_tabs a {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tline-height: 1.2;\r\n}\r\n\r\n.yd_tabs h5 {\r\n\tfont-size: 32px;\r\n\tfont-weight: 600;\r\n\tline-height: 1.2;\r\n\tmargin-bottom: 20px;\r\n}\r\n\r\n.yd_tabs .nav-tabs h2 {\r\n\tfont-size: 18px;\r\n\tfont-weight: 600;\r\n\tline-height: 1.2;\r\n\tmargin-bottom: 20px;\r\n\tpadding: 30px;\r\n}\r\n\r\n\r\n.yd_tabs .nav-item {\r\n\tpadding: 10px;\r\n}\r\n\r\n.yd_tabs p {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.yd_tabs .ar-icon {\r\n\t\tfloat: left;\r\n\t\twidth: 15%;\r\n\t}\r\n\r\n\t.yd_tabs .ar-icon img {\r\n\t\tmargin-top: 0;\r\n\t\tvertical-align: middle;\r\n\t}\r\n\r\n\t.yd_tabs .ar-text {\r\n\t\tfloat: right;\r\n\t\twidth: 85%;\r\n\t}\r\n\r\n\t.yd_tabs .ar-text h3 {\r\n\t\tfont-size: 18px;\r\n\t\tcolor: #364655;\r\n\t  font-weight: 600;\r\n\t  line-height: 1.2;\r\n\t  margin-bottom: 10px;\r\n\t}\r\n\r\n\t.yd_tabs .ar-text p {\r\n\t\tfont-size: 14px;\r\n\t  font-weight: 500;\r\n\t  line-height: 1.6;\r\n\t  color: #959597;\r\n\t}\r\n\r\n\r\n\t@media screen and (max-width: 576px) {\r\n\r\n\t  .yd_tabs .nav-tabs {\r\n\t    margin-bottom: 11px;\r\n\t  }\r\n\t  .yd_tabs .nav-tabs .nav-item {\r\n\t    width: auto !important;\r\n\t  }\r\n\t  .yd_tabs .nav-tabs.yd_tabs-right {\r\n\t    margin-bottom: 0;\r\n\t    margin-top: 10px;\r\n\t  }\r\n\r\n\t\t.yd_tabs .nav-tabs .nav-link {\r\n\t\t\tpadding: 20px;\r\n\t\t}\r\n\r\n\t\t.yd_tabs .ar-icon {\r\n\t\t\tfloat: left;\r\n\t\t\twidth: 25%;\r\n\t\t}\r\n\r\n\t\t.yd_tabs .ar-text {\r\n\t\t\tfloat: right;\r\n\t\t\twidth: 75%;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\r\n/*----------------------------------------------\r\n------------ Single Feature section ------------\r\n----------------------------------------------*/\r\n\r\n.ft_single {\r\n\tposition: relative;\r\n\tpadding: 100px 0 100px 0;\r\n}\r\n\r\n.yd_flex {\r\n\tdisplay: block;\r\n\ttext-align: center;\r\n}\r\n\r\n.yd_flex_1 {\r\n \t-webkit-box-flex:1;\r\n \t-ms-flex:1;\r\n \tflex:1;\r\n}\r\n\r\n.yd_flex_2 {\r\n\t-webkit-box-ordinal-group:2;\r\n\t-ms-flex-order:1;\r\n\torder:1\r\n}\r\n\r\n.yd_flex_1 .flex_content {\r\n\tmax-width: 420px;\r\n\tmargin: 0 auto;\r\n}\r\n\r\n.yd_flex_1 .flex_content h2 {\r\n\tfont-size: 32px;\r\n\tfont-weight: 700;\r\n\tline-height: 1.4;\r\n\tcolor: #364655;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.yd_flex_1 .flex_content p {\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tline-height: 1.4;\r\n\tcolor: #5f6368;\r\n\tmargin-bottom: 5px;\r\n}\r\n\r\n.flex_main {\r\n\tdisplay: flex;\r\n\tflex-wrap: wrap;\r\n\tjustify-content: center;\r\n}\r\n\r\n.flex_sub {\r\n\talign-items: center;\r\n\tflex-basis: calc(50% - 24px);\r\n  flex-direction: column;\r\n  justify-content: center;\r\n  margin: 10px;\r\n  padding: 15px 10px;\r\n  position: relative;\r\n\tbackground: rgb(248, 249, 250);\r\n  border: 1px solid transparent;\r\n  border-radius: 2px;\r\n  display: flex;\r\n\tcursor: pointer;\r\n  margin-bottom: 12px;\r\n  transition: box-shadow .3s ease-in-out;\r\n}\r\n\r\n.flex_sub:hover {\r\n\tbox-shadow:0 0 20px rgba(0, 0, 0, .1);\r\n}\r\n\r\n.flex_sub .sub_image {\r\n\tmargin: 0px 0 20px;\r\n}\r\n\r\n.flex_sub .sub_image img {\r\n\twidth: 60px;\r\n\theight: 60px;\r\n}\r\n\r\n.flex_sub .sub_text {\r\n\ttext-align: center;\r\n}\r\n\r\n.flex_sub .sub_text h4 {\r\n\tfont-size: 14px;\r\n\tfont-weight: 600;\r\n\tline-height: 1.2;\r\n\tcolor: #202124;\r\n\tmargin-bottom: 5px;\r\n}\r\n\r\n.flex_sub .sub_text p {\r\n\tfont-size: 13px;\r\n\tfont-weight: 500;\r\n\tline-height: 1.4;\r\n\tcolor: #5f6368;\r\n\tmargin: 5px 0;\r\n}\r\n\r\n/*------------- YD Clients Styling ---------------*/\r\n\r\n.yd_clients {\r\n\tpadding: 50px 0;\r\n}\r\n\r\n.yd_clients_intro {\r\n\ttext-align: center;\r\n\tmax-width: 600px;\r\n\tmargin: 0 auto;\r\n\tmargin-bottom: 50px;\r\n}\r\n\r\n.yd_clients_intro h4 {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: #8798ab;\r\n\tline-height: 1.4;\r\n\tletter-spacing: 1px;\r\n\ttext-transform: uppercase;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.yd_clients_intro h2 {\r\n\tfont-size: 32px;\r\n  font-weight: 300;\r\n  color: #3a3a47;\r\n  line-height: 1.4;\r\n  margin-bottom: 15px;\r\n}\r\n\r\n.yd_clients_intro p {\r\n\tfont-size: 18px;\r\n\tfont-weight: 400;\r\n\tcolor: #787878;\r\n\tline-height: 1.6;\r\n\tletter-spacing: 0;\r\n}\r\n\r\n.flx_2 {\r\n\tmax-width: 600px;\r\n\tmargin: 0 auto;\r\n\tmargin-top: 25px;\r\n\ttext-align: center;\r\n}\r\n\r\n.yd_clients .flx_2 h1 {\r\n\tfont-size: 26px;\r\n\tfont-weight: 300;\r\n\tcolor: #3a3a47;\r\n\tline-height: 1.4;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.yd_clients .flx_2 h2 {\r\n\tfont-size: 16px;\r\n\tfont-weight: 300;\r\n\tcolor: #3a3a47;\r\n\tline-height: 1.4;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.yd_clients .flx_2 a {\r\n\tfont-family: 'Open Sans';\r\n\tfont-size: 14px;\r\n\tfont-weight: 400;\r\n\tcolor: #047aed;\r\n\tline-height: 1.4;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.yd_clients .review-img {\r\n\tdisplay: flex;\r\n\theight: 100%;\r\n}\r\n\r\n.yd_clients .review-img .review-img-inner {\r\n\tmargin: auto;\r\n}\r\n\r\n.yd_clients .review-img img {\r\n\twidth: 120px;\r\n}\r\n\r\n.yd_clients .client-list {\r\n\tmargin-top: 50px;\r\n}\r\n\r\n.yd_clients .client-list ul {\r\n\tlist-style-type: none;\r\n\ttext-align: center;\r\n}\r\n\r\n.yd_clients .client-list ul li {\r\n\tdisplay: inline;\r\n\tmargin: 0 20px;\r\n}\r\n\r\n.yd_clients .client-list ul li img {\r\n  width: 100px;\r\n\topacity: 0.6;\r\n\tcursor: pointer;\r\n}\r\n\r\n\r\n\r\n\r\n/*------------------------------------------------\r\n--------------- Review Card Styling --------------\r\n-------------------------------------------------*/\r\n\r\n.yd_rev_slides {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\tpadding: 50px 0;\r\n\tbackground: #F7F7F8;\r\n\tbackground: linear-gradient(to right, rgba(255, 255, 255, 0.3), rgba(0, 0, 0, 0)), url(../images/bg.jpg) no-repeat center center;\r\n\tbackground-size: cover;\r\n\tbackground-position: top;\r\n}\r\n\r\n.rev_intro {\r\n\tdisplay: flex;\r\n\theight: 100%;\r\n\tmax-width: 360px;\r\n}\r\n\r\n.rev_intro_inner {\r\n\tmargin: auto;\r\n}\r\n\r\n.rev_intro h4 {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: #8798ab;\r\n\tline-height: 1.4;\r\n\tletter-spacing: 1px;\r\n\ttext-transform: uppercase;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.rev_intro h2 {\r\n\tfont-size: 32px;\r\n  font-weight: 300;\r\n  color: #3a3a47;\r\n  line-height: 1.4;\r\n  margin-bottom: 15px;\r\n}\r\n\r\n.rev_intro p {\r\n\tfont-size: 18px;\r\n\tfont-weight: 400;\r\n\tcolor: #787878;\r\n\tline-height: 1.6;\r\n\tletter-spacing: 0;\r\n}\r\n\r\n.reviews {\r\n\tbackground: #FFFFFF;\r\n\tpadding: 40px;\r\n}\r\n\r\n.rev_box {\r\n\tmargin: 0 10px;\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.rev_attr {\r\n\tdisplay: flex;\r\n\tmargin-top: 55px;\r\n}\r\n\r\n.rev_img {\r\n\tdisplay: flex;\r\n}\r\n\r\n.rev_img .rev_img_inner {\r\n\tmargin: auto;\r\n}\r\n\r\n.rev_img img {\r\n\twidth: 50px;\r\n}\r\n\r\n.rev_footer {\r\n\tmargin-left: 25px;\r\n}\r\n\r\n\r\n.rev_text h1 {\r\n\tfont-size: 21px;\r\n\tfont-weight: 500;\r\n\tcolor: #787878;\r\n\tline-height: 1.6;\r\n\tletter-spacing: 0;\r\n\tmargin-bottom: 20px;\r\n}\r\n\r\n.rev_footer h2 {\r\n\tfont-size: 18px;\r\n\tfont-weight: 600;\r\n\tcolor: #565656;\r\n\tline-height: 1.4;\r\n\tmargin-bottom: 2px;\r\n}\r\n\r\n.rev_footer h6 {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: #808080;\r\n\tline-height: 1.4;\r\n\tmargin-bottom: 3px;\r\n}\r\n\r\n.rev_footer a {\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 12px;\r\n\tfont-weight: 500;\r\n\tcolor: #047aed;\r\n\tposition: relative;\r\n\tdisplay: inline-block;\r\n\ttext-decoration: none;\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------\r\n--------------------- Faq Section Styling -------------------\r\n------------------------------------------------------------*/\r\n\r\n.yd_faqs {\r\n\tpadding: 50px 0;\r\n\t/*background: #f7f7f8;*/\r\n  background: #fff;\r\n}\r\n\r\n.yd_faqs .yd_flx2 {\r\n\tmin-height: 500px;\r\n\tdisplay: flex;\r\n}\r\n\r\n.yd_faqs .yd_flx2 .flx_1 {\r\n\tline-height: normal;\r\n\tpadding: 0 100px;\r\n\tmin-height: 300px;\r\n}\r\n\r\n.yd_faqs .faq_intro {\r\n\tmax-width: 600px;\r\n\tmargin-bottom: 50px;\r\n}\r\n\r\n.yd_faqs .faq_inner h2 {\r\n\tfont-size: 32px;\r\n\tfont-weight: 300;\r\n\tcolor: #111;\r\n\tline-height: 1.2;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.yd_faqs .faq_inner p {\r\n\tfont-size: 16px;\r\n\tfont-weight: 400;\r\n\tcolor: rgba(0, 0, 0, 0.5);\r\n\tline-height: 1.6;\r\n\tmargin: 15px 0;\r\n}\r\n\r\n.yd_faqs .faq_inner h5 {\r\n\tfont-size: 16px;\r\n\tfont-weight: 400;\r\n\tcolor: rgba(0, 0, 0, 0.5);\r\n\tline-height: 1.6;\r\n\tmargin-top: 20px;\r\n\tdisplay: inline;\r\n}\r\n\r\n.yd_faqs .faq_inner a {\r\n\tdisplay: inline;\r\n\tfont-family: 'Open Sans';\r\n\tcolor: #047aed;\r\n\tfont-size: 14px;\r\n\tfont-weight: 400;\r\n\ttext-decoration: none;\r\n}\r\n\r\n#accordion .card-header:after {\r\n  font-family: 'ionicons';\r\n  content: \"\\f209\";\r\n  float: right;\r\n\ttransition: 0.5s;\r\n}\r\n#accordion .card-header.collapsed:after {\r\n  /* symbol for \"collapsed\" panels */\r\n  content: \"\\f218\";\r\n\ttransition: 0.5s;\r\n}\r\n\r\n#accordion .card {\r\n\tborder-radius: 0;\r\n\tborder: 0;\r\n}\r\n\r\n#accordion .card-header {\r\n\tpadding: 30px 0;\r\n\tbackground: #f7f7f8;\r\n\tborder-bottom: 2px solid rgba(0,0,0,.03);\r\n\tcursor: pointer;\r\n}\r\n\r\n#accordion .card-header .card-title {\r\n\tfont-family: 'Open Sans';\r\n\tfont-size: 18px;\r\n\tcolor: rgba(0, 0, 0, 0.75);\r\n\tfont-weight: 500;\r\n\tline-height: 1.4;\r\n}\r\n\r\n#accordion .card-body {\r\n\tpadding: 30px 0;\r\n\tbackground: #f7f7f8;\r\n}\r\n\r\n#accordion .card-body p {\r\n\tfont-family: 'Roboto';\r\n\tfont-size: 16px;\r\n\tcolor: rgba(0, 0, 0, 0.6);\r\n\tfont-weight: 400;\r\n\tline-height: 2;\r\n}\r\n\r\n.faq_alt {\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.faq_alt #accordion .card-header {\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.faq_alt #accordion .card-body {\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------\r\n------------------- Split Features Styling ------------------\r\n------------------------------------------------------------*/\r\n\r\n\r\n.split_features {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n}\r\n\r\n.split_features .yd_flx2 {\r\n\tmin-height: 500px;\r\n}\r\n\r\n.split_features .yd_flx2 .flx_1 {\r\n\tline-height: normal;\r\n\tbackground: #eee;\r\n\tpadding: 0 100px;\r\n\tmin-height: 300px;\r\n}\r\n\r\n.split_features .yd_flx2 .flx_1 .split_text {\r\n\tdisplay: flex;\r\n\tmargin: auto;\r\n\theight: 100%;\r\n}\r\n\r\n.split_features .yd_flx2 .flx_1 .split_text_inner {\r\n\tmargin: auto; /* Important */\r\n}\r\n\r\n\r\n.split_features .yd_flx2 .flx_1 h2 {\r\n\tfont-family: 'Roboto' !important;\r\n\tfont-size: 38px;\r\n\tfont-weight: 300;\r\n\tcolor: #111;\r\n\tline-height: 1.4;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.split_features .yd_flx2 .flx_1 p {\r\n\tfont-family: 'Roboto' !important;\r\n\tfont-size: 17px;\r\n\tfont-weight: 400;\r\n\tcolor: #777;\r\n\tline-height: 1.6;\r\n\tmargin-top: 15px;\r\n}\r\n\r\n.split_features .yd_flx2 .flx_2 {\r\n\tpadding: 0;\r\n\tbackground: url(../images/hg.jpg) no-repeat center center;\r\n\tbackground-size: cover;\r\n\tmin-height: 300px;\r\n\r\n}\r\n\r\n\r\n\r\n/*-----------------------------------------------------------\r\n------------------- YD Custom Features Styling ------------------\r\n------------------------------------------------------------*/\r\n\r\n\r\n.ft_cst2 {\r\n\tpadding: 100px 0;\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.ft_cst2 .split_text {\r\n\tdisplay: flex;\r\n\tmax-width: 480px;\r\n\theight: 100%;\r\n}\r\n\r\n.ft_cst2 .split_text_inner {\r\n\tmargin: auto; /* Important */\r\n}\r\n\r\n.ft_cst2 .split_text_inner h4 {\r\n\tfont-size: 13px !important;\r\n\tfont-weight: 600;\r\n\ttext-transform: uppercase;\r\n\tletter-spacing: 1px;\r\n\tcolor: #607d9c;\r\n\tline-height: 1.3;\r\n\tmargin: 0 0 20px 0;\r\n}\r\n\r\n.ft_cst2 .split_text_inner h2 {\r\n\tfont-size: 28px !important;\r\n\tfont-weight: 300;\r\n\tcolor: #445555;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.ft_cst2 .split_text_inner p {\r\n\tfont-size: 18px !important;\r\n\tfont-weight: 400 !important;\r\n\tcolor: rgba(0, 0, 0, 0.5);\r\n\tline-height: 1.6;\r\n\tmargin: 20px 0 0 0;\r\n}\r\n\r\n.ft_cst2 .split_text_inner .btn-action {\r\n\tmargin: 20px 0 0 0;\r\n}\r\n\r\n.ft_cst2 .f-text {\r\n\tline-height: normal;\r\n\ttext-align: center;\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.ft_cst2 .flex-inner {\r\n\tmargin: 0;\r\n}\r\n\r\n.ft_cst2 .f-text {\r\n\tline-height: normal;\r\n\ttext-align: center;\r\n\tbackground: #FFFFFF;\r\n\tmargin-top: 0;\r\n}\r\n\r\n.ft_cst2 .flex-inner .f-image {\r\n\tmargin-top: 50px !important;\r\n}\r\n\r\n\r\n\r\n/*-----------------------------------------------------------\r\n------------------- YD Custom Features Styling ------------------\r\n------------------------------------------------------------*/\r\n\r\n.yd_pricing {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\tpadding: 100px 0;\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.yd_pricing .flex-inner {\r\n\tmargin: 0;\r\n}\r\n\r\n.yd_pricing .flex-inner .f-text {\r\n\tmargin-top: 50px;\r\n\ttext-align: center;\r\n}\r\n\r\n.yd_pricing .split_text {\r\n\tdisplay: flex;\r\n\tmax-width: 600px;\r\n\tmargin: 0 auto;\r\n\theight: 100%;\r\n}\r\n\r\n.yd_pricing .split_text_inner {\r\n\tmargin: auto; /* Important */\r\n}\r\n\r\n.yd_pricing .split_text_inner h4 {\r\n\tfont-size: 14px;\r\n\tfont-weight: 600;\r\n\tcolor: #8798ab;\r\n\tletter-spacing: 1px;\r\n\ttext-transform: uppercase;\r\n\tmargin-bottom: 10px;\r\n}\r\n\r\n.yd_pricing .split_text_inner h2 {\r\n\tfont-size: 34px !important;\r\n\tfont-weight: 300;\r\n\tcolor: #445555;\r\n\tline-height: 1.3;\r\n}\r\n\r\n.yd_pricing .split_text_inner p {\r\n\tfont-size: 16px !important;\r\n\tfont-weight: 400 !important;\r\n\tcolor: rgba(0, 0, 0, 0.5);\r\n\tline-height: 1.6;\r\n\tmargin-top: 20px;\r\n}\r\n\r\n.yd_pricing .split_text_inner h6 {\r\n\tfont-size: 12px;\r\n\tfont-weight: 400;\r\n\tcolor: #8798ab;\r\n\tdisplay: inline;\r\n}\r\n\r\n.yd_pricing .btn-link {\r\n\tfont-family: 'Open Sans';\r\n\tcolor: #047aed;\r\n\tfont-size: 13px;\r\n\tfont-weight: 400;\r\n\ttext-decoration: none;\r\n}\r\n\r\n.yd_pricing .split_text_inner .btn-action {\r\n\tmargin: 20px 0 0 0;\r\n}\r\n\r\n.yd_pricing .f-text {\r\n\tline-height: normal;\r\n\tbackground: #FFFFFF;\r\n}\r\n\r\n.yd_pricing .prc_box {\r\n\ttext-align: center;\r\n\tpadding: 50px;\r\n\tmax-width: 320px;\r\n\tmargin: 0 auto;\r\n\tmargin-bottom: 0;\r\n\tborder-radius: 5px;\r\n\tbackground: #047aed;\r\n\tborder: 1px solid #ececec;\r\n\tbox-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);\r\n\tcursor: pointer;\r\n}\r\n\r\n.yd_pricing .prc_box .prc h1 {\r\n\tfont-family: 'Roboto';\r\n\tfont-size: 48px;\r\n\tfont-weight: 500;\r\n\tcolor: #F7F7F8;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.yd_pricing .prc_box .prc span {\r\n\tfont-family: 'Open Sans';\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: #F7F7F8;\r\n}\r\n\r\n.yd_pricing .prc_box .prc_text h2 {\r\n\tfont-size: 24px;\r\n\tfont-weight: 600;\r\n\tcolor: #F7F7F8;\r\n\tline-height: 1.6;\r\n\tmargin-top: 20px;\r\n}\r\n\r\n.yd_pricing .prc_box p {\r\n\tfont-size: 16px;\r\n\tfont-weight: 400;\r\n\tcolor: rgba(255, 255, 255, 0.8);\r\n\tline-height: 1.6;\r\n\tmargin-top: 10px;\r\n}\r\n\r\n\r\n/*---------------- Pricing Tables ------------------*/\r\n\r\n\r\n/* ----- Pricing Tables Styling Starts ----- */\r\n\r\n.pricing-section {\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\tpadding-top: 100px;\r\n  background: #F7F7F8;\r\n/*\tbackground: #FFFFFF;*/\r\n}\r\n\r\n\r\n.pricing-intro h1 {\r\n\tfont-size: 28px;\r\n\tcolor: #445555;\r\n\tfont-weight: 300;\r\n\tline-height: 1.4;\r\n\tmargin-bottom: 20px;\r\n}\r\n\r\n\r\n.pricing-intro p {\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tline-height: 1.6;\r\n\tletter-spacing: 0.01em;\r\n\tcolor: #8B92AB;\r\n\tmargin-top: 10px;\r\n\tmargin-bottom: 50px;\r\n}\r\n\r\n.pricing-details {\r\n\tpadding: 50px 0 0 0;\r\n}\r\n\r\n.pricing-section .table-left, .pricing-section .table-right {\r\n\tpadding: 15%;\r\n\tmargin: 0 auto;\r\n\tmargin-bottom: 30px;\r\n/*\tbackground-color: #F7F7F8;*/\r\n  background-color: #fff;\r\n\tborder: transparent;\r\n\tmax-width: 400px;\r\n}\r\n\r\n.table-left h3, .table-right h3 {\r\n\tfont-size: 25px;\r\n\tfont-weight: 600;\r\n\tcolor: #505050;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.table-left p, .table-right p {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: #505050;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.pricing-section .table-right {\r\n\tcolor: #FFFFFF !important;\r\n\tbackground-color: #047aed;\r\n}\r\n\r\n.pricing-section .table-right h3, .pricing-section .table-right p {\r\n\tcolor: #FFFFFF !important;\r\n}\r\n\r\n\r\n.table-left .icon, .table-right .icon {\r\n\tpadding: 50px 50px 40px 50px;\r\n}\r\n\r\n.table-left .icon img, .table-right .icon img {\r\n\twidth: 60px;\r\n\theight: 60px;\r\n\tmargin: 0 auto;\r\n}\r\n\r\n.table-left .pricing-details span, .table-right .pricing-details span {\r\n\tdisplay: inline-block;\r\n\tfont-family: 'Open Sans';\r\n\tfont-size: 42px;\r\n\tfont-weight: 500;\r\n\tcolor: #505050;\r\n\tmargin-bottom: 15px;\r\n}\r\n\r\n.sub_note {\r\n\tfont-family: 'Open Sans';\r\n  padding-bottom:5px;\r\n\tfont-size: 10px;\r\n\tfont-weight: 400;\r\n\tcolor: #505050;\r\n}\r\n\r\n.sub_deposit {\r\n\tfont-family: 'Open Sans';\r\n  padding-bottom:5px;\r\n\tfont-size: 10px;\r\n\tfont-weight: 400;\r\n\tcolor: #505050;\r\n}\r\n\r\n.sub_span {\r\n\tfont-family: 'Open Sans';\r\n  padding-top:10px;\r\n\tfont-size: 15px;\r\n\tfont-weight: 400;\r\n\tcolor: #505050;\r\n}\r\n\r\n.sub_span_alt {\r\n\tcolor: #FFFFFF;\r\n}\r\n\r\n.table-left .pricing-details h2, .table-right .pricing-details h2 {\r\n\tfont-size: 21px;\r\n\tfont-weight: 500;\r\n\tcolor: #505050;\r\n\tmargin-bottom: 30px;\r\n}\r\n\r\n.table-left .pricing-details p, .table-right .pricing-details p {\r\n\tfont-size: 14px;\r\n\tfont-weight: 300;\r\n\tcolor: #505050;\r\n\tletter-spacing: 1px;\r\n\tline-height: 1.4;\r\n}\r\n\r\n.table-right .pricing-details h2, .table-right .pricing-details span {\r\n\tcolor: #FFFFFF !important;\r\n}\r\n\r\n\r\n.pricing-section .table-left, .pricing-section .table-right {\r\n\tmargin-top: 20px;\r\n}\r\n\r\n.pricing-section .table-center {\r\n\tmargin-top: 0;\r\n}\r\n\r\n.pricing-section .btn-action {\r\n\tbackground-color: #4285f4;\r\n\tborder-color: #4285f4;\r\n}\r\n\r\n.btn-white {\r\n\tcolor: #047aed;\r\n\tbackground-color: #FFFFFF !important;\r\n\tborder-color: #FFFFFF !important;\r\n}\r\n\r\n\r\n.pricing-section .btn-white:hover {\r\n\tcolor: #555da8;\r\n}\r\n\r\n.pricing-section .refund-txt {\r\n\tfont-size: 12px;\r\n\tfont-weight: 500;\r\n\tcolor: #505050;\r\n}\r\n\r\n\r\n\r\n/* ------------ Bact-to-Top Styling Starts Here ------------*/\r\n\r\n\r\n.footer {\r\n\tbackground: #040E1A;\r\n\tbackground: #303c42;\r\n\tpadding: 35px 0;\r\n\tborder-top: 2px solid rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.footer-inner {\r\n\tbackground: #1e266d;\r\n}\r\n\r\n.footer .footer-logo {\r\n\ttext-align: center;\r\n}\r\n\r\n.footer .footer-logo h2 {\r\n\tfont-size: 18px;\r\n\tfont-weight: 500;\r\n\tcolor: #e5e5e5;\r\n\ttext-transform: uppercase;\r\n\tline-height: 1.4;\r\n\tletter-spacing: 1px;\r\n}\r\n\r\n.footer p {\r\n\tfont-size: 24px;\r\n\tfont-weight: 700;\r\n\tcolor: #e5e5e5;\r\n\tline-height: 1.4;\r\n\tmargin-top: 0;\r\n}\r\n\r\n/* ------------ Bact-to-Top Styling Starts Here ------------*/\r\n\r\n.back-to-top {\r\n\tposition: fixed;\r\n\tbottom: 30px;\r\n\tright: 30px;\r\n\tfont-family: 'Montserrat';\r\n\tfont-size: 11px;\r\n\tfont-weight: 600;\r\n\ttext-transform: uppercase;\r\n\tcolor: #FFFFFF;\r\n\tline-height: 1.4;\r\n\tdisplay: inline-block;\r\n\tpadding: 1.2rem 1.2rem;\r\n\tmargin-top: 0;\r\n\tborder-radius: 0;\r\n\tbackground: url(../icons/up.png) center top 0.5rem no-repeat #047aed;\r\n\ttext-decoration: none;\r\n\t-webkit-transition: 200ms;\r\n\t-moz-transition: 200ms;\r\n\t-o-transition: 200ms;\r\n\ttransition: 200ms;\r\n}\r\n\r\n.back-to-top:hover {\r\n  color: #FFFFFF;\r\n\ttext-decoration: none;\r\n}\r\n\r\n\r\n.footer ul {\r\n\tlist-style-type: none;\r\n\ttext-align: center;\r\n\tmargin-top: 0;\r\n}\r\n\r\n.footer .footer-menu {\r\n\ttext-align: center;\r\n\tmargin: 20px 0;\r\n}\r\n\r\n.footer .footer-links ul {\r\n\ttext-align: center;\r\n}\r\n\r\n.footer ul li {\r\n\tfont-family: \"Montserrat\";\r\n  font-size: 16px;\r\n  font-weight: 500;\r\n\tletter-spacing: 0;\r\n  display: inline-block;\r\n\tmargin-left: 10px;\r\n  margin-right: 10px;\r\n}\r\n\r\n.footer ul li a {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tline-height: 24px;\r\n\ttext-transform: uppercase;\r\n  position: relative;\r\n  display: inline-block;\r\n  color: #FFFFFF;\r\n  text-decoration: none;\r\n}\r\n\r\n.footer ul li a:hover {\r\n  text-decoration: none;\r\n  color: #97a6b5;\r\n}\r\n\r\n.footer .footer-links ul li {\r\n\tmargin-left: 10px;\r\n  margin-right: 10px;\r\n}\r\n\r\n.footer .footer-links ul li a img {\r\n\twidth: 24px;\r\n\tvertical-align: middle;\r\n  padding-right:5px;\r\n}\r\n\r\n\r\n\r\n\r\n/*------------------------------------------\r\n-------------- Media Queries ---------------\r\n------------------------------------------*/\r\n\r\n@media only screen and (min-width: 767px) {\r\n\r\n\r\n\t.logo .tld {\r\n\t\tbackground: #047aed;\r\n\t}\r\n\r\n\t.navbar-nav {\r\n\t\t\tmargin-top: 0;\r\n\t\t}\r\n\r\n\t.navbar-nav .nav-item {\r\n\t\tmargin-top: 0;\r\n\t\tmargin-right: 15px;\r\n\t  font-size: 0.85rem;\r\n\t  font-weight: 400;\r\n\t}\r\n\r\n\t.btn-nav {\r\n\t\tmargin: 0;\r\n\t}\r\n\r\n\t.container-s {\r\n\t\tpadding-left: 20px;\r\n\t\tpadding-right: 20px;\r\n\t}\r\n\r\n\t.container-m {\r\n\t\tpadding-left: 20px;\r\n\t\tpadding-right: 20px;\r\n\t}\r\n\r\n\t.hero-inner h2 {\r\n\t\tfont-size: 38px;\r\n\t}\r\n\r\n\t.home .hero-content {\r\n\t\tpadding: 75px 0 0 0;\r\n\t}\r\n\r\n\t.home-2 {\r\n\t\tpadding: 150px 0 50px 0;\r\n\t}\r\n\r\n\t.home-2 .hero-form #contactForm {\r\n\t\tfloat: right;\r\n\t}\r\n\r\n\t.home-2 .hero-content .hero-content-inner {\r\n\t\ttext-align: left;\r\n\t}\r\n\r\n\t.home-3 .hero-content .hero-content-inner {\r\n\t\ttext-align: left;\r\n\t}\r\n\r\n\t.home-3 .hero-img img {\r\n\t\tbox-shadow: 0 0px 30px rgba(0, 0, 0, 0.2);\r\n\t}\r\n\r\n\t.lbl-services {\r\n\t\tpadding: 100px 0 50px 0;\r\n\t}\r\n\r\n\t.service-intro h1 {\r\n\t\tfont-size: 34px;\r\n\t}\r\n\r\n\t.card_single {\r\n\t\twidth: calc(33.333% - 2px);\r\n\t}\r\n\r\n\t.flex-split {\r\n\t\tpadding: 100px 0;\r\n\t}\r\n\r\n\t.flex-intro h2 {\r\n\t\tfont-size: 34px;\r\n\t}\r\n\r\n\t.flex-inner {\r\n\t\tposition: relative;\r\n    display: -webkit-box;\r\n    display: -ms-flexbox;\r\n    display: flex;\r\n    -webkit-box-align: center;\r\n    -ms-flex-align: center;\r\n    align-items: center;\r\n\t\tmargin: 75px 0 0 0;\r\n\t}\r\n\r\n\t.flex-inner .f-image {\r\n    -webkit-box-flex: 0;\r\n\t\t-ms-flex: 0 0 400px;\r\n\t\tflex: 0 0 400px;\r\n\t}\r\n\r\n\t.ft_cst2 .split_text_inner h2 {\r\n\t\tfont-size: 34px !important;\r\n\t}\r\n\r\n\t.yd_pricing .flex-inner .f-text {\r\n\t\tmargin-top: 0;\r\n\t\ttext-align: left;\r\n\t}\r\n\r\n\t.yd_clients {\r\n\t\tpadding: 100px 0;\r\n\t}\r\n\r\n\t.yd_rev_slides {\r\n\t\tpadding: 100px 0;\r\n\t}\r\n\r\n\t.rev_text h1 {\r\n\t\tfont-size: 24px;\r\n\t}\r\n\r\n\t.reviews {\r\n\t\tpadding: 50px;\r\n\t}\r\n\r\n\t.cta_box .cta_box_inner h2 {\r\n\t\tfont-size: 32px;\r\n\t}\r\n\r\n\t.cta_sub .cta_sub_inner h2 {\r\n\t\tfont-size: 32px;\r\n\t}\r\n\r\n\t.ft_cst2 .flex-inner .f-image {\r\n\t\tmargin-top: 0 !important;\r\n\t\t-webkit-box-flex: 0;\r\n\t  -ms-flex: 0 0 400px;\r\n\t  flex: 0 0 400px;\r\n\t}\r\n\r\n\t.yd_vid_ft {\r\n\t\tpadding: 100px 0;\r\n\t}\r\n\r\n\t.yd_pricing .f-image {\r\n\t\t-webkit-box-flex: 0;\r\n\t\t-ms-flex: 0 0 360px;\r\n\t\tflex: 0 0 360px;\r\n\t}\r\n\r\n\t.yd_pricing .split_text_inner h2 {\r\n\t\tfont-size: 34px !important;\r\n\t}\r\n\r\n\t.yd_pricing .split_text_inner p {\r\n\t\tfont-size: 16px !important;\r\n\t}\r\n\r\n\t.yd_pricing .prc_box {\r\n\t\tmargin-bottom: 0;\r\n\t}\r\n\r\n\t.flex-inner .f-text h2 {\r\n\t\tmargin-top: 0;\r\n\t}\r\n\r\n\t.yd_faqs {\r\n\t\tpadding: 100px 0;\r\n\t}\r\n\r\n\t.yd_tabs {\r\n\t\tpadding: 100px 0;\r\n\t}\r\n\r\n\t.yd_pricing .split_text_inner h2 {\r\n\t\tfont-size: 34px !important;\r\n\t}\r\n\r\n\t.yd_pricing .split_text_inner p {\r\n\t\tfont-size: 18px !important;\r\n\t}\r\n\r\n\t.yd_pricing .prc_box {\r\n\t\tmargin-bottom: 0;\r\n\t}\r\n\r\n\t.pricing-intro h1 {\r\n\t\tfont-size: 34px;\r\n\t}\r\n\r\n\t.flex-inner .f-text h2 {\r\n\t\tfont-size: 24px;\r\n\t}\r\n\r\n\t.flex-inner .f-text  p {\r\n\t\tfont-size: 16px;\r\n\t\tfont-weight: 500;\r\n\t}\r\n\r\n\t.yd_flex {\r\n\t\tposition: relative;\r\n    display: -webkit-box;\r\n    display: -ms-flexbox;\r\n    display: flex;\r\n\t\ttext-align: left;\r\n    -webkit-box-align: center;\r\n    -ms-flex-align: center;\r\n    align-items: center;\r\n\t}\r\n\r\n\t.yd_flex .yd_flex_2 {\r\n    -webkit-box-flex: 0;\r\n    -ms-flex: 0 0 568px;\r\n    flex: 0 0 568px;\r\n\t}\r\n\r\n\t.yd_flex_1 .flex_content {\r\n\t\tmax-width: 420px;\r\n\t\tmargin: 0;\r\n\t}\r\n\r\n\t.left {\r\n\t\tpadding: 50px;\r\n\t}\r\n\r\n\t.flx_content h2 {\r\n\t\tfont-size: 24px;\r\n\t}\r\n\r\n\t.flex_main {\r\n\t\tdisplay: flex;\r\n\t}\r\n\r\n\t.flex_sub {\r\n\t  margin: 12px;\r\n\t  padding: 32px;\r\n\t}\r\n\r\n\t.flex_sub .sub_text h4 {\r\n\t\tfont-size: 16px;\r\n\t}\r\n\r\n\t.left {\r\n\t\tflex: 1 0 0;\r\n\t}\r\n\r\n\t.right {\r\n\t\tflex: 1 0 0;\r\n\t\tflex-direction: column;\r\n\t}\r\n\r\n\t.right .sec-one {\r\n\t\tflex: 1;\r\n\t}\r\n\r\n\t.right .sec-two {\r\n\t\tflex: 1;\r\n\t}\r\n\r\n\t.right .sec-two {\r\n\t\tpadding: 25px;\r\n\t}\r\n\r\n\r\n\t.flx_2 {\r\n\t\tmargin-top: 25px;\r\n\t\ttext-align: center;\r\n\t}\r\n\r\n\t.yd_clients .review-img img {\r\n\t\twidth: 120px;\r\n\t}\r\n\r\n\t.split_features .yd_flx2 .flx_1 {\r\n\t\tflex: 1 0 0;\r\n\t\tflex-basis: 50%;\r\n\t}\r\n\r\n\t.split_features .yd_flx2 .flx_2 {\r\n\t\tflex: 1 0 0;\r\n\t\tflex-basis: 50%;\r\n\t}\r\n\r\n\t.yd_faqs .yd_flx2 .flx_1 {\r\n\t\tflex: 1 0 0;\r\n\t\tflex-basis: 50%;\r\n\t}\r\n\r\n\t.yd_faqs .yd_flx2 .flx_2 {\r\n\t\tflex: 1 0 0;\r\n\t\tflex-basis: 50%;\r\n\t}\r\n\r\n\r\n\t.footer .footer-logo {\r\n\t\ttext-align: left;\r\n\t}\r\n\r\n\t.footer .footer-menu {\r\n\t\ttext-align: right;\r\n\t\tmargin: 0;\r\n\t}\r\n\r\n\t.footer .footer-links ul {\r\n\t\ttext-align: right;\r\n\t}\r\n\r\n}\r\n\r\n@media only screen and (min-width: 480px) {\r\n\r\n\t.container-s {\r\n\t\tpadding-left: 40px;\r\n\t\tpadding-right: 40px;\r\n\t}\r\n\r\n\t.flex-inner .f-text {\r\n\t-webkit-box-flex: 1;\r\n\t-ms-flex: 1;\r\n\tflex: 1;\r\n\ttext-align: left;\r\n}\r\n\r\n\r\n}\r\n\r\n@media only screen and (min-width: 24em) {\r\n\r\n\t.prk-circle {\r\n\t\twidth: 360px;\r\n\t\theight: 360px;\r\n\t}\r\n\r\n\t.txt-box h2 {\r\n\t\tfont-size: 21px;\r\n\t\tfont-weight: 500;\r\n\t}\r\n\r\n\t.txt-box .btn-action {\r\n\t\tpadding: 10px 24px;\r\n\t\tfont-size: 12px;\r\n\t\tmargin: 25px 10px 0 0;\r\n\t}\r\n\r\n\t.txt-box ul#countdown li span {\r\n\t\tfont-size: 38px;\r\n\t}\r\n\r\n\t.txt-box ul#countdown li.seperator {\r\n\t\tfont-size: 32px;\r\n\t}\r\n\r\n\t.txt-box ul#countdown li p {\r\n\t\tfont-size: 14px;\r\n\t}\r\n}\r\n\r\n@media only screen and (min-width: 768px) and (max-width: 1024px) {\r\n\r\n\t.card_single {\r\n\t\ttext-align: center;\r\n\t\tpadding: 10px;\r\n\t}\r\n\r\n\t.yd_flex .yd_flex_2 {\r\n\t\t-webkit-box-flex: 0;\r\n\t\t-ms-flex: 0 0 420px;\r\n\t\tflex: 0 0 420px;\r\n\t}\r\n\r\n\t.home-split .flx_2 {\r\n\t\tmin-width: 100%;\r\n\t}\r\n\r\n}\r\n\r\n@media only screen and (min-width: 1024px) {\r\n\r\n\t.home-3 .hero-img img {\r\n\t\tbox-shadow: 0 0px 30px rgba(0, 0, 0, 0.2);\r\n\t}\r\n\r\n\t.home-split .flx_2 {\r\n\t\tmin-width: inherit;\r\n\t}\r\n\r\n\t.ft_cst2 .flex-inner .f-image {\r\n\t\tmargin-top: 0 !important;\r\n\t\t-webkit-box-flex: 0;\r\n\t\t-ms-flex: 0 0 540px;\r\n\t\tflex: 0 0 540px;\r\n\t}\r\n\r\n\t.cta_box .cta_box_inner {\r\n\t\tpadding: 0;\r\n\t}\r\n\r\n\t.yd_pricing .f-image {\r\n\t\t\t-webkit-box-flex: 0;\r\n\t\t\t-ms-flex: 0 0 540px;\r\n\t\t\tflex: 0 0 540px;\r\n\t}\r\n\r\n\t.left {\r\n\t\tpadding: 100px;\r\n\t}\r\n\r\n\t.right .sec-two {\r\n\t\tpadding: 50px;\r\n\t}\r\n\r\n\r\n\t.flx_content h2 {\r\n\t\tfont-size: 30px;\r\n\t}\r\n\r\n\t.yd_tabs .ar-icon {\r\n\t\tfloat: left;\r\n\t\twidth: 20%;\r\n\t}\r\n\r\n\t.yd_tabs .ar-text {\r\n\t\tfloat: right;\r\n\t\twidth: 80%;\r\n\t}\r\n}\r\n\r\n@media only screen and (max-width: 420px) {\r\n\r\n\t.form {\r\n\t\ttext-align: center;\r\n\t}\r\n\r\n\t.form input {\r\n\t  padding: 0 75px 0 20px;\r\n\t}\r\n\r\n\t.form .submit-button {\r\n\t  margin-left: 0;\r\n\t\tmargin-top: 10px;\r\n\t}\r\n\r\n\t#chimp-email-error {\r\n\t    left: 5%;\r\n\t    bottom: -30%;\r\n\t}\r\n\r\n  .yd_cta_box #response {\r\n  \tposition: absolute;\r\n\t  left: 5%;\r\n\t  bottom: -50%;\r\n   }\r\n\r\n\t.yd_cta_box #chimp-email-error {\r\n\t\tleft: 15%;\r\n\t\tbottom: -25%;\r\n\t}\r\n\r\n}\r\n\r\n.team-image {\r\n  padding: 0px;\r\n}\r\n\r\n.laptimer-text {\r\n\tpadding: 15px;\r\n\tmargin-top: 5px;\r\n}\r\n\r\n.laptimer-text h3 {\r\n\tfont-size: 21px;\r\n\tfont-weight: 500;\r\n  text-align:center;\r\n\tcolor: #364655;\r\n}\r\n\r\n#interface .img-fluid {\r\n  margin-bottom:0px !important;\r\n}\r\n\r\n.laptimer-text p {\r\n  text-align:center;\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tcolor: rgb(129, 129, 152);\r\n\tline-height: 1.6;\r\n\tmargin-top: 15px;\r\n}\r\n.team-text {\r\n\tpadding: 15px;\r\n\tmargin-top: 15px;\r\n}\r\n\r\n.team-text h3 {\r\n\tfont-size: 21px;\r\n\tfont-weight: 500;\r\n  text-align:center;\r\n\tcolor: #364655;\r\n}\r\n\r\n.team-text p {\r\n  text-align:center;\r\n\tfont-size: 16px;\r\n\tfont-weight: 500;\r\n\tcolor: rgb(129, 129, 152);\r\n\tline-height: 1.6;\r\n\tmargin-top: 15px;\r\n}\r\n\r\n.team {\r\n  padding: 50px 0;\r\n\tposition: relative;\r\n}\r\n\r\n.questions {\r\n  text-align:center;\r\n    font-size: 14px;\r\n    font-weight: 500;\r\n    line-height: 1.6;\r\n    letter-spacing: 0.01em;\r\n    color: #818198;\r\n    max-width: 630px;\r\n    margin: 0 auto;\r\n    margin-top: 15px;\r\n    margin-bottom: 15px;\r\n}\r\n\r\n.listofbikes h4 {\r\n    font-size: 14px;\r\n    font-weight: 500;\r\n    color: rgba(0, 0, 0, 0.4);\r\n    line-height: 1.2;\r\n    letter-spacing: 1px;\r\n    margin-bottom: 10px;\r\n  }\r\n\r\n.img-fluid {\r\n      box-shadow: 0 0px 30px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.logos {\r\n  max-width: 100%;\r\n  height: auto;\r\n}\r\n\r\n.loop-video {\r\n  margin-top: 25px;\r\n}\r\n\r\n.cornering-shot {\r\n  display:block !important;\r\n}\r\n\r\n.track-info {\r\n\tfont-family: \"Open Sans\";\r\n\tfont-size: 14px;\r\n\tfont-weight: 600;\r\n  margin-bottom:25px;\r\n\tcolor: #047aed;\r\n\tposition: relative;\r\n  display: inline-block;\r\n  text-decoration: none;\r\n}\r\n\r\n.track-info::after {\r\n\tcontent: \"\";\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\tbottom: -20%;\r\n\theight: 1px;\r\n\twidth: 50px;\r\n\tbackground: #8798ab;\r\n\t-webkit-transition: 0.3s;\r\n\ttransition: 0.3s;\r\n}\r\n\r\n.track-info:hover::after {\r\n\twidth: 75px;\r\n}\r\n\r\n.bike-fluid {\r\n      max-width: 100%;\r\n    height: auto;\r\n}\r\n\r\n.drone-video {\r\n  box-shadow: 0 0px 30px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n#contact a {\r\n  color: #fff;\r\n  font-weight:600;\r\n}\r\n\r\n.reserving h1 {\r\n  text-align:left;\r\n}\r\n\r\n\r\n.signup-spacing {\r\n  padding-top:60px;\r\n}\r\n\r\n.fillout {\r\n  text-align:left;\r\n}\r\n\r\n.fillout label {\r\n  padding-bottom:10px;\r\n}\r\n\r\n.ack-txt {\r\n  color: rgba(0, 0, 0, 0.5) !important;\r\n  font-weight:400 !important;\r\n  text-align:left;\r\n}\r\n\r\n.ack {\r\n  display:block;\r\n}\r\n\r\n.row {\r\n  margin:0 !important;\r\n}\r\n.container-fluid {\r\n  padding:0 !important;\r\n}\r\n\r\n.navbar-logo {\r\n  height:2.5em;\r\n}\r\n\r\n.hero-content-inner p b {\r\nfont-weight: 700;\r\n}\r\n\r\n.payment .row {\r\nmargin-top:50px !important;\r\n}\r\n\r\n.announcement {\r\n  font-weight:600;\r\n  margin:1em;\r\n}\r\n\r\n.orderbutton {\r\nfont-family: \"Open Sans\";\r\n    font-size: 14px;\r\n    font-weight: 600;\r\n    color: #047aed;\r\n    position: relative;\r\n    display: inline-block;\r\n    text-decoration: none;\r\n  }\r\n\r\n.twitchiframe {\r\n  min-height: 300px;\r\n  width: 100%;\r\n  height: 100%;\r\n  top: 0;\r\n}\r\n\r\n.track {\r\n  font-weight: 300;\r\n  font-size:12px;\r\n  padding-bottom:20px;\r\n  line-height:1.5em;\r\n}\r\n\r\n.tracklink {\r\n  font-size:14px;\r\n  font-weight:700;\r\n  padding-top:10px;\r\n}\r\n\r\n.textlink {\r\n  font-weight:600;\r\n   text-decoration: underline;\r\n}\r\n\r\n.trackrow {\r\n  padding-bottom:20px;\r\n  padding-top:20px;\r\n}\r\n\r\n.what-alt {\r\n  background: #F7F7F8;\r\n}\r\n\r\n.markdown-body {\r\n  box-sizing: border-box;\r\n  min-width: 200px;\r\n  max-width: 980px;\r\n  margin: 0 auto;\r\n  padding: 45px;\r\n}\r\n\r\n@media (max-width: 767px) {\r\n  .markdown-body {\r\n    padding: 15px;\r\n  }\r\n}\r\n\r\n.code-example {\r\n  margin: 0;\r\n  padding: 0;\r\n  margin-bottom: 0px !important;\r\n  background-color: transparent !important;\r\n}\r\n\r\n.copyright {\r\n  color: #fff !important;\r\n  font-size:13px;\r\n  padding-bottom: 12px;\r\n}\r\n\r\na.trademarks {\r\n\tcolor: #fff !important;\r\n\tfont-weight:600;\r\n\tdisplay: inline-block;\r\n\ttext-decoration: underline;\r\n\tpadding: 0.8rem 0;\r\n}\r\n\r\n.highlight {\r\n  background: #fff !important;\r\n}\r\n"
  },
  {
    "path": "docs/assets/favicons/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n    <msapplication>\n        <tile>\n            <square150x150logo src=\"/assets/favicons/mstile-150x150.png\"/>\n            <TileColor>#da532c</TileColor>\n        </tile>\n    </msapplication>\n</browserconfig>\n"
  },
  {
    "path": "docs/assets/favicons/site.webmanifest",
    "content": "{\n    \"name\": \"\",\n    \"short_name\": \"\",\n    \"icons\": [\n        {\n            \"src\": \"/assets/favicons/android-chrome-192x192.png\",\n            \"sizes\": \"192x192\",\n            \"type\": \"image/png\"\n        },\n        {\n            \"src\": \"/assets/favicons/android-chrome-256x256.png\",\n            \"sizes\": \"256x256\",\n            \"type\": \"image/png\"\n        }\n    ],\n    \"theme_color\": \"#ffffff\",\n    \"background_color\": \"#ffffff\",\n    \"display\": \"standalone\"\n}\n"
  },
  {
    "path": "docs/assets/js/contact.js",
    "content": "\n\n$(function () {\n  \"use strict\";\n\n    $('#contact-form').validator();\n\n    $('#contact-form').on('submit', function (e) {\n        if (!e.isDefaultPrevented()) {\n            var url = \"assets/php/contact.php\";\n\n            $.ajax({\n                type: \"POST\",\n                url: url,\n                data: $(this).serialize(),\n                success: function (data)\n                {\n                    var messageAlert = 'alert-' + data.type;\n                    var messageText = data.message;\n\n                    var alertBox = '<div class=\"alert ' + messageAlert + ' alert-dismissable\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>' + messageText + '</div>';\n                    if (messageAlert && messageText) {\n                        $('#contact-form').find('.messages').html(alertBox);\n                        $('#contact-form')[0].reset();\n                    }\n                }\n            });\n            return false;\n        }\n    })\n});\n"
  },
  {
    "path": "docs/assets/js/custom.js",
    "content": "// Custom Scripts for Primal Template //\r\n\r\njQuery(function($) {\r\n    \"use strict\";\r\n\r\n\r\n        // get the value of the bottom of the #main element by adding the offset of that element plus its height, set it as a variable\r\n        var mainbottom = $('#main').offset().top;\r\n\r\n        // on scroll,\r\n        $(window).on('scroll',function(){\r\n\r\n        // we round here to reduce a little workload\r\n        stop = Math.round($(window).scrollTop());\r\n        if (stop > mainbottom) {\r\n            $('.navbar').addClass('past-main');\r\n            $('.navbar').addClass('effect-main')\r\n        } else {\r\n            $('.navbar').removeClass('past-main');\r\n       }\r\n\r\n      });\r\n\r\n\r\n  // Collapse navbar on click\r\n\r\n   $(document).on('click.nav','.navbar-collapse.in',function(e) {\r\n    if( $(e.target).is('a') ) {\r\n    $(this).removeClass('in').addClass('collapse');\r\n   }\r\n  });\r\n\r\n  /*-----------------------------------\r\n  ----------- Scroll To Top -----------\r\n  ------------------------------------*/\r\n\r\n    $(window).scroll(function () {\r\n      if ($(this).scrollTop() > 1000) {\r\n          $('#back-top').fadeIn();\r\n      } else {\r\n          $('#back-top').fadeOut();\r\n      }\r\n    });\r\n    // scroll body to 0px on click\r\n    $('#back-top').on('click', function () {\r\n      $('#back-top').tooltip('hide');\r\n      $('body,html').animate({\r\n          scrollTop: 0\r\n      }, 1500);\r\n      return false;\r\n    });\r\n\r\n\r\n  /*-------- Owl Carousel ---------- */\r\n    $(\".reviews\").owlCarousel({\r\n\r\n    slideSpeed : 200,\r\n    items: 1,\r\n    singleItem: true,\r\n    autoPlay : true,\r\n    pagination : false\r\n    });\r\n\r\n\r\n  /*-------- Owl Carousel ---------- */\r\n    $(\".review-cards\").owlCarousel({\r\n\r\n    slideSpeed : 200,\r\n    items: 1,\r\n    singleItem: true,\r\n    autoPlay : true,\r\n    pagination : false\r\n    });\r\n\r\n\r\n  /* ------ jQuery for Easing min -- */\r\n\r\n    // Smooth scrolling using jQuery easing\r\n    $('a.js-scroll-trigger[href*=\"#\"]:not([href=\"#\"])').on('click', function () {\r\n      if (location.pathname.replace(/^\\//, '') == this.pathname.replace(/^\\//, '') && location.hostname == this.hostname) {\r\n        var target = $(this.hash);\r\n        target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');\r\n        if (target.length) {\r\n          $('html, body').animate({\r\n            scrollTop: (target.offset().top - 54)\r\n          }, 1000, \"easeInOutExpo\");\r\n          return false;\r\n        }\r\n      }\r\n    });\r\n\r\n\r\n  /* --------- Wow Init ------ */\r\n\r\n  new WOW().init();\r\n\r\n\r\n  /* ------ Countdown ----- */\r\n\r\n   $('#countdown').countdown({\r\n       date: '12/12/2031 12:00:00',\r\n       offset: +2,\r\n     day: 'Day',\r\n     days: 'Days'\r\n   }, function () {\r\n       alert('Done!');\r\n   });\r\n\r\n\r\n/*----- Preloader ----- */\r\n\r\n  $(window).load(function() {\r\n\t\tsetTimeout(function() {\r\n      $('#loading').fadeOut('slow', function() {\r\n      });\r\n    }, 3000);\r\n  });\r\n\r\n\r\n/*----- Subscription Form ----- */\r\n\r\n$(document).ready(function() {\r\n  // jQuery Validation\r\n  $(\"#chimp-form\").validate({\r\n    // if valid, post data via AJAX\r\n    submitHandler: function(form) {\r\n      $.post(\"assets/php/subscribe.php\", { email: $(\"#email\").val() }, function(data) {\r\n        $('#response').html(data);\r\n      });\r\n    },\r\n    // all fields are required\r\n    rules: {\r\n      email: {\r\n        required: true,\r\n        email: true\r\n      }\r\n    }\r\n  });\r\n});\r\n\r\n// Accordion //\r\n\r\nfunction toggleChevron(e) {\r\n   $(e.target)\r\n     .prev('.panel-heading')\r\n     .find(\"span.glyphicon\")\r\n     .toggleClass('glyphicon-chevron-down glyphicon-chevron-right');\r\n }\r\n $('#accordion').on('hide.bs.collapse show.bs.collapse', toggleChevron);\r\n\r\n\r\n\r\n});\r\n"
  },
  {
    "path": "docs/assets/js/jquery-2.1.1.js",
    "content": "/*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */\n!function(a,b){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error(\"jQuery requires a window with a document\");return b(a)}:b(a)}(\"undefined\"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m=\"2.1.1\",n=function(a,b){return new n.fn.init(a,b)},o=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,p=/^-ms-/,q=/-([\\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:\"\",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for(\"boolean\"==typeof g&&(j=g,g=arguments[h]||{},h++),\"object\"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:\"jQuery\"+(m+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return\"function\"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return\"object\"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,\"isPrototypeOf\")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+\"\":\"object\"==typeof a||\"function\"==typeof a?h[i.call(a)]||\"object\":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf(\"use strict\")?(b=l.createElement(\"script\"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,\"ms-\").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?\"\":(a+\"\").replace(o,\"\")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,\"string\"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return\"string\"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(a,b){h[\"[object \"+b+\"]\"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return\"function\"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:\"array\"===c||0===b||\"number\"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=\"sizzle\"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C=\"undefined\",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",M=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",N=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",O=N.replace(\"w\",\"w#\"),P=\"\\\\[\"+M+\"*(\"+N+\")(?:\"+M+\"*([*^$|!~]?=)\"+M+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+O+\"))|)\"+M+\"*\\\\]\",Q=\":(\"+N+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+P+\")*)|.*)\\\\)|)\",R=new RegExp(\"^\"+M+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+M+\"+$\",\"g\"),S=new RegExp(\"^\"+M+\"*,\"+M+\"*\"),T=new RegExp(\"^\"+M+\"*([>+~]|\"+M+\")\"+M+\"*\"),U=new RegExp(\"=\"+M+\"*([^\\\\]'\\\"]*?)\"+M+\"*\\\\]\",\"g\"),V=new RegExp(Q),W=new RegExp(\"^\"+O+\"$\"),X={ID:new RegExp(\"^#(\"+N+\")\"),CLASS:new RegExp(\"^\\\\.(\"+N+\")\"),TAG:new RegExp(\"^(\"+N.replace(\"w\",\"w*\")+\")\"),ATTR:new RegExp(\"^\"+P),PSEUDO:new RegExp(\"^\"+Q),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+M+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+M+\"*(?:([+-]|)\"+M+\"*(\\\\d+)|))\"+M+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+L+\")$\",\"i\"),needsContext:new RegExp(\"^\"+M+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+M+\"*((?:-\\\\d)?\\\\d*)\"+M+\"*\\\\)|)(?=[^-]|$)\",\"i\")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,$=/^[^{]+\\{\\s*\\[native \\w/,_=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ab=/[+~]/,bb=/'|\\\\/g,cb=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+M+\"?|(\"+M+\")|.)\",\"ig\"),db=function(a,b,c){var d=\"0x\"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||\"string\"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&\"object\"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute(\"id\"))?s=r.replace(bb,\"\\\\$&\"):b.setAttribute(\"id\",s),s=\"[id='\"+s+\"'] \",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(\",\")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute(\"id\")}}}return i(a.replace(R,\"$1\"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+\" \")>d.cacheLength&&delete b[a.shift()],b[c+\" \"]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement(\"div\");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split(\"|\"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return\"input\"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return(\"input\"===c||\"button\"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?\"HTML\"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener(\"unload\",function(){m()},!1):g.attachEvent&&g.attachEvent(\"onunload\",function(){m()})),c.attributes=ib(function(a){return a.className=\"i\",!a.getAttribute(\"className\")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment(\"\")),!a.getElementsByTagName(\"*\").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML=\"<div class='a'></div><div class='a i'></div>\",a.firstChild.className=\"i\",2===a.getElementsByClassName(\"i\").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute(\"id\")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode(\"id\");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if(\"*\"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML=\"<select msallowclip=''><option selected=''></option></select>\",a.querySelectorAll(\"[msallowclip^='']\").length&&q.push(\"[*^$]=\"+M+\"*(?:''|\\\"\\\")\"),a.querySelectorAll(\"[selected]\").length||q.push(\"\\\\[\"+M+\"*(?:value|\"+L+\")\"),a.querySelectorAll(\":checked\").length||q.push(\":checked\")}),ib(function(a){var b=e.createElement(\"input\");b.setAttribute(\"type\",\"hidden\"),a.appendChild(b).setAttribute(\"name\",\"D\"),a.querySelectorAll(\"[name=d]\").length&&q.push(\"name\"+M+\"*[*^$|!~]?=\"),a.querySelectorAll(\":enabled\").length||q.push(\":enabled\",\":disabled\"),a.querySelectorAll(\"*,:x\"),q.push(\",.*:\")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,\"div\"),s.call(a,\"[s!='']:x\"),r.push(\"!=\",Q)}),q=q.length&&new RegExp(q.join(\"|\")),r=r.length&&new RegExp(r.join(\"|\")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,\"='$1']\"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c=\"\",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if(\"string\"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||\"\").replace(cb,db),\"~=\"===a[2]&&(a[3]=\" \"+a[3]+\" \"),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),\"nth\"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*(\"even\"===a[3]||\"odd\"===a[3])),a[5]=+(a[7]+a[8]||\"odd\"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||\"\":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(\")\",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return\"*\"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+\" \"];return b||(b=new RegExp(\"(^|\"+M+\")\"+a+\"(\"+M+\"|$)\"))&&y(a,function(a){return b.test(\"string\"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute(\"class\")||\"\")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?\"!=\"===b:b?(e+=\"\",\"=\"===b?e===c:\"!=\"===b?e!==c:\"^=\"===b?c&&0===e.indexOf(c):\"*=\"===b?c&&e.indexOf(c)>-1:\"$=\"===b?c&&e.slice(-c.length)===c:\"~=\"===b?(\" \"+e+\" \").indexOf(c)>-1:\"|=\"===b?e===c||e.slice(0,c.length+1)===c+\"-\":!1):!0}},CHILD:function(a,b,c,d,e){var f=\"nth\"!==a.slice(0,3),g=\"last\"!==a.slice(-4),h=\"of-type\"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?\"nextSibling\":\"previousSibling\",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p=\"only\"===a&&!o&&\"nextSibling\"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error(\"unsupported pseudo: \"+a);return e[u]?e(b):e.length>1?(c=[a,a,\"\",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,\"$1\"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||\"\")||fb.error(\"unsupported lang: \"+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute(\"xml:lang\")||b.getAttribute(\"lang\"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+\"-\");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&!!a.checked||\"option\"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&\"button\"===a.type||\"button\"===b},text:function(a){var b;return\"input\"===a.nodeName.toLowerCase()&&\"text\"===a.type&&(null==(b=a.getAttribute(\"type\"))||\"text\"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+\" \"];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R,\" \")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d=\"\";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&\"parentNode\"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||\"*\",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[\" \"],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:\" \"===a[i-2].type?\"*\":\"\"})).replace(R,\"$1\"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q=\"0\",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG(\"*\",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+\" \"];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n=\"function\"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&\"ID\"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split(\"\").sort(B).join(\"\")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement(\"div\"))}),ib(function(a){return a.innerHTML=\"<a href='#'></a>\",\"#\"===a.firstChild.getAttribute(\"href\")})||jb(\"type|href|height|width\",function(a,b,c){return c?void 0:a.getAttribute(b,\"type\"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML=\"<input/>\",a.firstChild.setAttribute(\"value\",\"\"),\"\"===a.firstChild.getAttribute(\"value\")})||jb(\"value\",function(a,b,c){return c||\"input\"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute(\"disabled\")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[\":\"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,w=/^.[^:#\\[\\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if(\"string\"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=\":not(\"+a+\")\"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if(\"string\"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+\" \"+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,\"string\"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if(\"string\"==typeof a){if(c=\"<\"===a[0]&&\">\"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?\"undefined\"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||\"string\"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?\"string\"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return n.dir(a,\"parentNode\",c)},next:function(a){return D(a,\"nextSibling\")},prev:function(a){return D(a,\"previousSibling\")},nextAll:function(a){return n.dir(a,\"nextSibling\")},prevAll:function(a){return n.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return n.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return n.dir(a,\"previousSibling\",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return\"Until\"!==a.slice(-5)&&(d=c),d&&\"string\"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a=\"string\"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);\"function\"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&\"string\"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[[\"resolve\",\"done\",n.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",n.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",n.Callbacks(\"memory\")]],c=\"pending\",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+\"With\"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+\"With\"](this===e?d:this,arguments),this},e[f[0]+\"With\"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler(\"ready\"),n(l).off(\"ready\"))))}});function I(){l.removeEventListener(\"DOMContentLoaded\",I,!1),a.removeEventListener(\"load\",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),\"complete\"===l.readyState?setTimeout(n.ready):(l.addEventListener(\"DOMContentLoaded\",I,!1),a.addEventListener(\"load\",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if(\"object\"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if(\"string\"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&\"string\"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d=\"data-\"+b.replace(O,\"-$1\").toLowerCase(),c=a.getAttribute(d),\"string\"==typeof c){try{c=\"true\"===c?!0:\"false\"===c?!1:\"null\"===c?null:+c+\"\"===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)\n},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,\"hasDataAttrs\"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf(\"data-\")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,\"hasDataAttrs\",!0)}return e}return\"object\"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf(\"-\")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||\"fx\")+\"queue\",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||\"fx\";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};\"inprogress\"===e&&(e=c.shift(),d--),e&&(\"fx\"===b&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks(\"once memory\").add(function(){L.remove(a,[b+\"queue\",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return\"string\"!=typeof a&&(b=a,a=\"fx\",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),\"fx\"===a&&\"inprogress\"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||\"fx\",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};\"string\"!=typeof a&&(b=a,a=void 0),a=a||\"fx\";while(g--)c=L.get(f[g],a+\"queueHooks\"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,R=[\"Top\",\"Right\",\"Bottom\",\"Left\"],S=function(a,b){return a=b||a,\"none\"===n.css(a,\"display\")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement(\"div\")),c=l.createElement(\"input\");c.setAttribute(\"type\",\"radio\"),c.setAttribute(\"checked\",\"checked\"),c.setAttribute(\"name\",\"t\"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML=\"<textarea>x</textarea>\",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U=\"undefined\";k.focusinBubbles=\"onfocusin\"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||\"\").match(E)||[\"\"],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(\".\")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||\"\").match(E)||[\"\"],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp(\"(^|\\\\.)\"+p.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&(\"**\"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,\"events\"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,\"type\")?b.type:b,r=j.call(b,\"namespace\")?b.namespace.split(\".\"):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(\".\")>=0&&(r=q.split(\".\"),q=r.shift(),r.sort()),k=q.indexOf(\":\")<0&&\"on\"+q,b=b[n.expando]?b:new n.Event(q,\"object\"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join(\".\"),b.namespace_re=b.namespace?new RegExp(\"(^|\\\\.)\"+r.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,\"events\")||{})[b.type]&&L.get(g,\"handle\"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,\"events\")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||\"click\"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||\"click\"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+\" \",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:\"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:\"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:\"focusin\"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:\"focusout\"},click:{trigger:function(){return\"checkbox\"===this.type&&this.click&&n.nodeName(this,\"input\")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,\"a\")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if(\"object\"==typeof a){\"string\"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&(\"string\"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+\".\"+d.namespace:d.origType,d.selector,d.handler),this;if(\"object\"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||\"function\"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,bb=/<([\\w:]+)/,cb=/<|&#?\\w+;/,db=/<(?:script|style|link)/i,eb=/checked\\s*(?:[^=]|=\\s*.checked.)/i,fb=/^$|\\/(?:java|ecma)script/i,gb=/^true\\/(.*)/,hb=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,ib={option:[1,\"<select multiple='multiple'>\",\"</select>\"],thead:[1,\"<table>\",\"</table>\"],col:[2,\"<table><colgroup>\",\"</colgroup></table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:[0,\"\",\"\"]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,\"table\")&&n.nodeName(11!==b.nodeType?b:b.firstChild,\"tr\")?a.getElementsByTagName(\"tbody\")[0]||a.appendChild(a.ownerDocument.createElement(\"tbody\")):a}function kb(a){return a.type=(null!==a.getAttribute(\"type\"))+\"/\"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute(\"type\"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],\"globalEval\",!b||L.get(b[c],\"globalEval\"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||\"*\"):a.querySelectorAll?a.querySelectorAll(b||\"*\"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();\"input\"===c&&T.test(a.type)?b.checked=a.checked:(\"input\"===c||\"textarea\"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,\"script\"),g.length>0&&mb(g,!i&&ob(a,\"script\")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if(\"object\"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement(\"div\")),g=(bb.exec(e)||[\"\",\"\"])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,\"<$1></$2>\")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=\"\"}else l.push(b.createTextNode(e));k.textContent=\"\",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),\"script\"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||\"\")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,\"script\")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent=\"\");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if(\"string\"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(ab,\"<$1></$2>\");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&\"string\"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,\"script\"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,\"script\"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||\"\")&&!L.access(h,\"globalEval\")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,\"\")))}return this}}),n.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],\"display\");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),\"none\"!==c&&c||(qb=(qb||n(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp(\"^(\"+Q+\")(?!px)[a-z%]+$\",\"i\"),wb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(\"\"!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+\"\":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement(\"div\"),f=l.createElement(\"div\");if(f.style){f.style.backgroundClip=\"content-box\",f.cloneNode(!0).style.backgroundClip=\"\",k.clearCloneStyle=\"content-box\"===f.style.backgroundClip,e.style.cssText=\"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute\",e.appendChild(f);function g(){f.style.cssText=\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute\",f.innerHTML=\"\",d.appendChild(e);var g=a.getComputedStyle(f,null);b=\"1%\"!==g.top,c=\"4px\"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement(\"div\"));return c.style.cssText=f.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",c.style.marginRight=c.style.width=\"0\",f.style.width=\"1px\",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp(\"^(\"+Q+\")(.*)$\",\"i\"),Bb=new RegExp(\"^([+-])=(\"+Q+\")\",\"i\"),Cb={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Db={letterSpacing:\"0\",fontWeight:\"400\"},Eb=[\"Webkit\",\"O\",\"Moz\",\"ms\"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||\"px\"):b}function Hb(a,b,c,d,e){for(var f=c===(d?\"border\":\"content\")?4:\"width\"===b?1:0,g=0;4>f;f+=2)\"margin\"===c&&(g+=n.css(a,c+R[f],!0,e)),d?(\"content\"===c&&(g-=n.css(a,\"padding\"+R[f],!0,e)),\"margin\"!==c&&(g-=n.css(a,\"border\"+R[f]+\"Width\",!0,e))):(g+=n.css(a,\"padding\"+R[f],!0,e),\"padding\"!==c&&(g+=n.css(a,\"border\"+R[f]+\"Width\",!0,e)));return g}function Ib(a,b,c){var d=!0,e=\"width\"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g=\"border-box\"===n.css(a,\"boxSizing\",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?\"border\":\"content\"),d,f)+\"px\"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,\"olddisplay\"),c=d.style.display,b?(f[g]||\"none\"!==c||(d.style.display=\"\"),\"\"===d.style.display&&S(d)&&(f[g]=L.access(d,\"olddisplay\",tb(d.nodeName)))):(e=S(d),\"none\"===c&&e||L.set(d,\"olddisplay\",e?c:n.css(d,\"display\"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&\"none\"!==d.style.display&&\"\"!==d.style.display||(d.style.display=b?f[g]||\"\":\"none\"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,\"opacity\");return\"\"===c?\"1\":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":\"cssFloat\"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&\"get\"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,\"string\"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f=\"number\"),null!=c&&c===c&&(\"number\"!==f||n.cssNumber[h]||(c+=\"px\"),k.clearCloneStyle||\"\"!==c||0!==b.indexOf(\"background\")||(i[b]=\"inherit\"),g&&\"set\"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&\"get\"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),\"normal\"===e&&b in Db&&(e=Db[b]),\"\"===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each([\"height\",\"width\"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,\"display\"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,\"border-box\"===n.css(a,\"boxSizing\",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:\"inline-block\"},xb,[a,\"marginRight\"]):void 0}),n.each({margin:\"\",padding:\"\",border:\"Width\"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f=\"string\"==typeof c?c.split(\" \"):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return\"boolean\"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||\"swing\",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?\"\":\"px\")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,\"\"),b&&\"auto\"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp(\"^(?:([+-])=|)(\"+Q+\")([a-z%]*)$\",\"i\"),Pb=/queueHooks$/,Qb=[Vb],Rb={\"*\":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?\"\":\"px\"),g=(n.cssNumber[a]||\"px\"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||\".5\",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e[\"margin\"+c]=e[\"padding\"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb[\"*\"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,\"fxshow\");c.queue||(h=n._queueHooks(a,\"fx\"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,\"fx\").length||h.empty.fire()})})),1===a.nodeType&&(\"height\"in b||\"width\"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,\"display\"),k=\"none\"===j?L.get(a,\"olddisplay\")||tb(a.nodeName):j,\"inline\"===k&&\"none\"===n.css(a,\"float\")&&(o.display=\"inline-block\")),c.overflow&&(o.overflow=\"hidden\",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||\"toggle\"===e,e===(p?\"hide\":\"show\")){if(\"show\"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))\"inline\"===(\"none\"===j?tb(a.nodeName):j)&&(o.display=j);else{q?\"hidden\"in q&&(p=q.hidden):q=L.access(a,\"fxshow\",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,\"fxshow\");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start=\"width\"===d||\"height\"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&\"expand\"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=[\"*\"]):a=a.split(\" \");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&\"object\"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:\"number\"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue=\"fx\"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css(\"opacity\",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,\"finish\"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return\"string\"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||\"fx\",[]),this.each(function(){var b=!0,e=null!=a&&a+\"queueHooks\",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||\"fx\"),this.each(function(){var b,c=L.get(this),d=c[a+\"queue\"],e=c[a+\"queueHooks\"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each([\"toggle\",\"show\",\"hide\"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||\"boolean\"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb(\"show\"),slideUp:Tb(\"hide\"),slideToggle:Tb(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||\"fx\",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement(\"input\"),b=l.createElement(\"select\"),c=b.appendChild(l.createElement(\"option\"));a.type=\"checkbox\",k.checkOn=\"\"!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement(\"input\"),a.value=\"t\",a.type=\"radio\",k.radioValue=\"t\"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&\"get\"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&\"set\"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+\"\"),c):void n.removeAttr(a,b))\n},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&\"radio\"===b&&n.nodeName(a,\"input\")){var c=a.value;return a.setAttribute(\"type\",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{\"for\":\"htmlFor\",\"class\":\"className\"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&\"set\"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&\"get\"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute(\"tabindex\")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\\t\\r\\n\\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=\"string\"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||\"\").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(\" \"+c.className+\" \").replace(ac,\" \"):\" \")){f=0;while(e=b[f++])d.indexOf(\" \"+e+\" \")<0&&(d+=e+\" \");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||\"string\"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||\"\").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(\" \"+c.className+\" \").replace(ac,\" \"):\"\")){f=0;while(e=b[f++])while(d.indexOf(\" \"+e+\" \")>=0)d=d.replace(\" \"+e+\" \",\" \");g=a?n.trim(d):\"\",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return\"boolean\"==typeof b&&\"string\"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if(\"string\"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||\"boolean\"===c)&&(this.className&&L.set(this,\"__className__\",this.className),this.className=this.className||a===!1?\"\":L.get(this,\"__className__\")||\"\")})},hasClass:function(a){for(var b=\" \"+a+\" \",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(\" \"+this[c].className+\" \").replace(ac,\" \").indexOf(b)>=0)return!0;return!1}});var bc=/\\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e=\"\":\"number\"==typeof e?e+=\"\":n.isArray(e)&&(e=n.map(e,function(a){return null==a?\"\":a+\"\"})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&\"set\"in b&&void 0!==b.set(this,e,\"value\")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&\"get\"in b&&void 0!==(c=b.get(e,\"value\"))?c:(c=e.value,\"string\"==typeof c?c.replace(bc,\"\"):null==c?\"\":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,\"value\");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f=\"select-one\"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute(\"disabled\"))||c.parentNode.disabled&&n.nodeName(c.parentNode,\"optgroup\"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each([\"radio\",\"checkbox\"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute(\"value\")?\"on\":a.value})}),n.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,\"**\"):this.off(b,a||\"**\",c)}});var cc=n.now(),dc=/\\?/;n.parseJSON=function(a){return JSON.parse(a+\"\")},n.parseXML=function(a){var b,c;if(!a||\"string\"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,\"text/xml\")}catch(d){b=void 0}return(!b||b.getElementsByTagName(\"parsererror\").length)&&n.error(\"Invalid XML: \"+a),b};var ec,fc,gc=/#.*$/,hc=/([?&])_=[^&]*/,ic=/^(.*?):[ \\t]*([^\\r\\n]*)$/gm,jc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,kc=/^(?:GET|HEAD)$/,lc=/^\\/\\//,mc=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,nc={},oc={},pc=\"*/\".concat(\"*\");try{fc=location.href}catch(qc){fc=l.createElement(\"a\"),fc.href=\"\",fc=fc.href}ec=mc.exec(fc.toLowerCase())||[];function rc(a){return function(b,c){\"string\"!=typeof b&&(c=b,b=\"*\");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])\"+\"===d[0]?(d=d.slice(1)||\"*\",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function sc(a,b,c,d){var e={},f=a===oc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return\"string\"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e[\"*\"]&&g(\"*\")}function tc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function uc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while(\"*\"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader(\"Content-Type\"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+\" \"+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function vc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if(\"*\"===f)f=i;else if(\"*\"!==i&&i!==f){if(g=j[i+\" \"+f]||j[\"* \"+f],!g)for(e in j)if(h=e.split(\" \"),h[1]===f&&(g=j[i+\" \"+h[0]]||j[\"* \"+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a[\"throws\"])b=g(b);else try{b=g(b)}catch(l){return{state:\"parsererror\",error:g?l:\"No conversion from \"+i+\" to \"+f}}}return{state:\"success\",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:fc,type:\"GET\",isLocal:jc.test(ec[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":pc,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":n.parseJSON,\"text xml\":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?tc(tc(a,n.ajaxSettings),b):tc(n.ajaxSettings,a)},ajaxPrefilter:rc(nc),ajaxTransport:rc(oc),ajax:function(a,b){\"object\"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks(\"once memory\"),q=k.statusCode||{},r={},s={},t=0,u=\"canceled\",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=ic.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||fc)+\"\").replace(gc,\"\").replace(lc,ec[1]+\"//\"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||\"*\").toLowerCase().match(E)||[\"\"],null==k.crossDomain&&(h=mc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===ec[1]&&h[2]===ec[2]&&(h[3]||(\"http:\"===h[1]?\"80\":\"443\"))===(ec[3]||(\"http:\"===ec[1]?\"80\":\"443\")))),k.data&&k.processData&&\"string\"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),sc(nc,k,b,v),2===t)return v;i=k.global,i&&0===n.active++&&n.event.trigger(\"ajaxStart\"),k.type=k.type.toUpperCase(),k.hasContent=!kc.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?\"&\":\"?\")+k.data,delete k.data),k.cache===!1&&(k.url=hc.test(d)?d.replace(hc,\"$1_=\"+cc++):d+(dc.test(d)?\"&\":\"?\")+\"_=\"+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader(\"If-Modified-Since\",n.lastModified[d]),n.etag[d]&&v.setRequestHeader(\"If-None-Match\",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader(\"Content-Type\",k.contentType),v.setRequestHeader(\"Accept\",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+(\"*\"!==k.dataTypes[0]?\", \"+pc+\"; q=0.01\":\"\"):k.accepts[\"*\"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u=\"abort\";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=sc(oc,k,b,v)){v.readyState=1,i&&m.trigger(\"ajaxSend\",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort(\"timeout\")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,\"No Transport\");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||\"\",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=uc(k,v,f)),u=vc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader(\"Last-Modified\"),w&&(n.lastModified[d]=w),w=v.getResponseHeader(\"etag\"),w&&(n.etag[d]=w)),204===a||\"HEAD\"===k.type?x=\"nocontent\":304===a?x=\"notmodified\":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x=\"error\",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+\"\",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?\"ajaxSuccess\":\"ajaxError\",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger(\"ajaxComplete\",[v,k]),--n.active||n.event.trigger(\"ajaxStop\")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,\"json\")},getScript:function(a,b){return n.get(a,void 0,b,\"script\")}}),n.each([\"get\",\"post\"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,\"body\")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var wc=/%20/g,xc=/\\[\\]$/,yc=/\\r?\\n/g,zc=/^(?:submit|button|image|reset|file)$/i,Ac=/^(?:input|select|textarea|keygen)/i;function Bc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||xc.test(a)?d(a,e):Bc(a+\"[\"+(\"object\"==typeof e?b:\"\")+\"]\",e,c,d)});else if(c||\"object\"!==n.type(b))d(a,b);else for(e in b)Bc(a+\"[\"+e+\"]\",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?\"\":b,d[d.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Bc(c,a[c],b,e);return d.join(\"&\").replace(wc,\"+\")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,\"elements\");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(\":disabled\")&&Ac.test(this.nodeName)&&!zc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(yc,\"\\r\\n\")}}):{name:b.name,value:c.replace(yc,\"\\r\\n\")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Cc=0,Dc={},Ec={0:200,1223:204},Fc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on(\"unload\",function(){for(var a in Dc)Dc[a]()}),k.cors=!!Fc&&\"withCredentials\"in Fc,k.ajax=Fc=!!Fc,n.ajaxTransport(function(a){var b;return k.cors||Fc&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Cc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c[\"X-Requested-With\"]||(c[\"X-Requested-With\"]=\"XMLHttpRequest\");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Dc[g],b=f.onload=f.onerror=null,\"abort\"===a?f.abort():\"error\"===a?d(f.status,f.statusText):d(Ec[f.status]||f.status,f.statusText,\"string\"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b(\"error\"),b=Dc[g]=b(\"abort\");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/(?:java|ecma)script/},converters:{\"text script\":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter(\"script\",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\")}),n.ajaxTransport(\"script\",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n(\"<script>\").prop({async:!0,charset:a.scriptCharset,src:a.url}).on(\"load error\",c=function(a){b.remove(),c=null,a&&e(\"error\"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Gc=[],Hc=/(=)\\?(?=&|$)|\\?\\?/;n.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var a=Gc.pop()||n.expando+\"_\"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter(\"json jsonp\",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Hc.test(b.url)?\"url\":\"string\"==typeof b.data&&!(b.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Hc.test(b.data)&&\"data\");return h||\"jsonp\"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Hc,\"$1\"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?\"&\":\"?\")+b.jsonp+\"=\"+e),b.converters[\"script json\"]=function(){return g||n.error(e+\" was not called\"),g[0]},b.dataTypes[0]=\"json\",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Gc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),\"script\"):void 0}),n.parseHTML=function(a,b,c){if(!a||\"string\"!=typeof a)return null;\"boolean\"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Ic=n.fn.load;n.fn.load=function(a,b,c){if(\"string\"!=typeof a&&Ic)return Ic.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(\" \");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&\"object\"==typeof b&&(e=\"POST\"),g.length>0&&n.ajax({url:a,type:e,dataType:\"html\",data:b}).done(function(a){f=arguments,g.html(d?n(\"<div>\").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Jc=a.document.documentElement;function Kc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,\"position\"),l=n(a),m={};\"static\"===k&&(a.style.position=\"relative\"),h=l.offset(),f=n.css(a,\"top\"),i=n.css(a,\"left\"),j=(\"absolute\"===k||\"fixed\"===k)&&(f+i).indexOf(\"auto\")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),\"using\"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Kc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return\"fixed\"===n.css(c,\"position\")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],\"html\")||(d=a.offset()),d.top+=n.css(a[0],\"borderTopWidth\",!0),d.left+=n.css(a[0],\"borderLeftWidth\",!0)),{top:b.top-d.top-n.css(c,\"marginTop\",!0),left:b.left-d.left-n.css(c,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Jc;while(a&&!n.nodeName(a,\"html\")&&\"static\"===n.css(a,\"position\"))a=a.offsetParent;return a||Jc})}}),n.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(b,c){var d=\"pageYOffset\"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Kc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each([\"top\",\"left\"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+\"px\":c):void 0})}),n.each({Height:\"height\",Width:\"width\"},function(a,b){n.each({padding:\"inner\"+a,content:b,\"\":\"outer\"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||\"boolean\"!=typeof d),g=c||(d===!0||e===!0?\"margin\":\"border\");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement[\"client\"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body[\"scroll\"+a],e[\"scroll\"+a],b.body[\"offset\"+a],e[\"offset\"+a],e[\"client\"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return n});var Lc=a.jQuery,Mc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Mc),b&&a.jQuery===n&&(a.jQuery=Lc),n},typeof b===U&&(a.jQuery=a.$=n),n});\n"
  },
  {
    "path": "docs/assets/js/jquery.accordion.js",
    "content": "/*!\n * jQuery Accordion 0.0.1\n * (c) 2014 Victor Fernandez <victor@vctrfrnndz.com>\n * MIT Licensed.\n */\n\n;(function ( $, window, document, undefined ) {\n\n    var pluginName = 'accordion',\n        defaults = {\n            transitionSpeed: 300,\n            transitionEasing: 'ease',\n            controlElement: '[data-control]',\n            contentElement: '[data-content]',\n            groupElement: '[data-accordion-group]',\n            singleOpen: true\n        };\n\n    function Accordion(element, options) {\n        this.element = element;\n        this.options = $.extend({}, defaults, options);\n        this._defaults = defaults;\n        this._name = pluginName;\n        this.init();\n    }\n\n    Accordion.prototype.init = function () {\n        var self = this,\n            opts = self.options;\n\n        var $accordion = $(self.element),\n            $controls = $accordion.find('> ' + opts.controlElement),\n            $content =  $accordion.find('> ' + opts.contentElement);\n\n        var accordionParentsQty = $accordion.parents('[data-accordion]').length,\n            accordionHasParent = accordionParentsQty > 0;\n\n        var closedCSS = { 'max-height': 0, 'overflow': 'hidden' };\n\n        var CSStransitions = supportsTransitions();\n\n        function debounce(func, threshold, execAsap) {\n            var timeout;\n\n            return function debounced() {\n                var obj = this,\n                    args = arguments;\n\n                function delayed() {\n                    if (!execAsap) func.apply(obj, args);\n                    timeout = null;\n                };\n\n                if (timeout) clearTimeout(timeout);\n                else if (execAsap) func.apply(obj, args);\n\n                timeout = setTimeout(delayed, threshold || 100);\n            };\n        }\n\n        function supportsTransitions() {\n            var b = document.body || document.documentElement,\n                s = b.style,\n                p = 'transition';\n\n            if (typeof s[p] == 'string') {\n                return true;\n            }\n\n            var v = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms'];\n\n            p = 'Transition';\n\n            for (var i=0; i<v.length; i++) {\n                if (typeof s[v[i] + p] == 'string') {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        function requestAnimFrame(cb) {\n            if(window.requestAnimationFrame){\n                requestAnimationFrame(cb);\n            } else if (window.webkitRequestAnimationFrame) {\n                webkitRequestAnimationFrame(cb);\n            } else if (window.mozRequestAnimationFrame) {\n                mozRequestAnimationFrame(cb);\n            } else {\n                setTimeout(cb, 1000 / 60);\n            }\n        }\n\n        function toggleTransition($el, remove) {\n            if(!remove) {\n                $content.css({\n                    '-webkit-transition': 'max-height ' + opts.transitionSpeed + 'ms ' + opts.transitionEasing,\n                    'transition': 'max-height ' + opts.transitionSpeed + 'ms ' + opts.transitionEasing\n                });\n            } else {\n                $content.css({\n                    '-webkit-transition': '',\n                    'transition': ''\n                });\n            }\n        }\n\n        function calculateHeight($el) {\n            var height = 0;\n\n            $el.children().each(function() {\n                height = height + $(this).outerHeight(true);\n            });\n\n            $el.data('oHeight', height);\n        }\n\n        function updateParentHeight($parentAccordion, $currentAccordion, qty, operation) {\n            var $content = $parentAccordion.filter('.open').find('> [data-content]'),\n                $childs = $content.find('[data-accordion].open > [data-content]'),\n                $matched;\n\n            if(!opts.singleOpen) {\n                $childs = $childs.not($currentAccordion.siblings('[data-accordion].open').find('> [data-content]'));\n            }\n\n            $matched = $content.add($childs);\n\n            if($parentAccordion.hasClass('open')) {\n                $matched.each(function() {\n                    var currentHeight = $(this).data('oHeight');\n\n                    switch (operation) {\n                        case '+':\n                            $(this).data('oHeight', currentHeight + qty);\n                            break;\n                        case '-':\n                            $(this).data('oHeight', currentHeight - qty);\n                            break;\n                        default:\n                            throw 'updateParentHeight method needs an operation';\n                    }\n\n                    $(this).css('max-height', $(this).data('oHeight'));\n                });\n            }\n        }\n\n        function refreshHeight($accordion) {\n            if($accordion.hasClass('open')) {\n                var $content = $accordion.find('> [data-content]'),\n                    $childs = $content.find('[data-accordion].open > [data-content]'),\n                    $matched = $content.add($childs);\n\n                calculateHeight($matched);\n\n                $matched.css('max-height', $matched.data('oHeight'));\n            }\n        }\n\n        function closeAccordion($accordion, $content) {\n            $accordion.trigger('accordion.close');\n            \n            if(CSStransitions) {\n                if(accordionHasParent) {\n                    var $parentAccordions = $accordion.parents('[data-accordion]');\n\n                    updateParentHeight($parentAccordions, $accordion, $content.data('oHeight'), '-');\n                }\n\n                $content.css(closedCSS);\n\n                $accordion.removeClass('open');\n            } else {\n                $content.css('max-height', $content.data('oHeight'));\n\n                $content.animate(closedCSS, opts.transitionSpeed);\n\n                $accordion.removeClass('open');\n            }\n        }\n\n        function openAccordion($accordion, $content) {\n            $accordion.trigger('accordion.open');\n            if(CSStransitions) {\n                toggleTransition($content);\n\n                if(accordionHasParent) {\n                    var $parentAccordions = $accordion.parents('[data-accordion]');\n\n                    updateParentHeight($parentAccordions, $accordion, $content.data('oHeight'), '+');\n                }\n\n                requestAnimFrame(function() {\n                    $content.css('max-height', $content.data('oHeight'));\n                });\n\n                $accordion.addClass('open');\n            } else {\n                $content.animate({\n                    'max-height': $content.data('oHeight')\n                }, opts.transitionSpeed, function() {\n                    $content.css({'max-height': 'none'});\n                });\n\n                $accordion.addClass('open');\n            }\n        }\n\n        function closeSiblingAccordions($accordion) {\n            var $accordionGroup = $accordion.closest(opts.groupElement);\n\n            var $siblings = $accordion.siblings('[data-accordion]').filter('.open'),\n                $siblingsChildren = $siblings.find('[data-accordion]').filter('.open');\n\n            var $otherAccordions = $siblings.add($siblingsChildren);\n\n            $otherAccordions.each(function() {\n                var $accordion = $(this),\n                    $content = $accordion.find(opts.contentElement);\n\n                closeAccordion($accordion, $content);\n            });\n\n            $otherAccordions.removeClass('open');\n        }\n\n        function toggleAccordion() {\n            var isAccordionGroup = (opts.singleOpen) ? $accordion.parents(opts.groupElement).length > 0 : false;\n\n            calculateHeight($content);\n\n            if(isAccordionGroup) {\n                closeSiblingAccordions($accordion);\n            }\n\n            if($accordion.hasClass('open')) {\n                closeAccordion($accordion, $content);\n            } else {\n                openAccordion($accordion, $content);\n            }\n        }\n\n        function addEventListeners() {\n            $controls.on('click', toggleAccordion);\n            \n            $controls.on('accordion.toggle', function() {\n                if(opts.singleOpen && $controls.length > 1) {\n                    return false;\n                }\n                \n                toggleAccordion();\n            });\n            \n            $controls.on('accordion.refresh', function() {\n                refreshHeight($accordion);\n            });\n\n            $(window).on('resize', debounce(function() {\n                refreshHeight($accordion);\n            }));\n        }\n\n        function setup() {\n            $content.each(function() {\n                var $curr = $(this);\n\n                if($curr.css('max-height') != 0) {\n                    if(!$curr.closest('[data-accordion]').hasClass('open')) {\n                        $curr.css({ 'max-height': 0, 'overflow': 'hidden' });\n                    } else {\n                        toggleTransition($curr);\n                        calculateHeight($curr);\n\n                        $curr.css('max-height', $curr.data('oHeight'));\n                    }\n                }\n            });\n\n\n            if(!$accordion.attr('data-accordion')) {\n                $accordion.attr('data-accordion', '');\n                $accordion.find(opts.controlElement).attr('data-control', '');\n                $accordion.find(opts.contentElement).attr('data-content', '');\n            }\n        }\n\n        setup();\n        addEventListeners();\n    };\n\n    $.fn[pluginName] = function ( options ) {\n        return this.each(function () {\n            if (!$.data(this, 'plugin_' + pluginName)) {\n                $.data(this, 'plugin_' + pluginName,\n                new Accordion( this, options ));\n            }\n        });\n    }\n\n})( jQuery, window, document );\n"
  },
  {
    "path": "docs/assets/js/live.js",
    "content": " /*\r\n  Live.js - One script closer to Designing in the Browser\r\n  Written for Handcraft.com by Martin Kool (@mrtnkl).\r\n\r\n  Version 4.\r\n  Recent change: Made stylesheet and mimetype checks case insensitive.\r\n\r\n  http://livejs.com\r\n  http://livejs.com/license (MIT)  \r\n  @livejs\r\n\r\n  Include live.js#css to monitor css changes only.\r\n  Include live.js#js to monitor js changes only.\r\n  Include live.js#html to monitor html changes only.\r\n  Mix and match to monitor a preferred combination such as live.js#html,css  \r\n\r\n  By default, just include live.js to monitor all css, js and html changes.\r\n  \r\n  Live.js can also be loaded as a bookmarklet. It is best to only use it for CSS then,\r\n  as a page reload due to a change in html or css would not re-include the bookmarklet.\r\n  To monitor CSS and be notified that it has loaded, include it as: live.js#css,notify\r\n*/\r\n(function () {\r\n\r\n  var headers = { \"Etag\": 1, \"Last-Modified\": 1, \"Content-Length\": 1, \"Content-Type\": 1 },\r\n      resources = {},\r\n      pendingRequests = {},\r\n      currentLinkElements = {},\r\n      oldLinkElements = {},\r\n      interval = 1000,\r\n      loaded = false,\r\n      active = { \"html\": 1, \"css\": 1, \"js\": 1 };\r\n\r\n  var Live = {\r\n\r\n    // performs a cycle per interval\r\n    heartbeat: function () {      \r\n      if (document.body) {        \r\n        // make sure all resources are loaded on first activation\r\n        if (!loaded) Live.loadresources();\r\n        Live.checkForChanges();\r\n      }\r\n      setTimeout(Live.heartbeat, interval);\r\n    },\r\n\r\n    // loads all local css and js resources upon first activation\r\n    loadresources: function () {\r\n\r\n      // helper method to assert if a given url is local\r\n      function isLocal(url) {\r\n        var loc = document.location,\r\n            reg = new RegExp(\"^\\\\.|^\\/(?!\\/)|^[\\\\w]((?!://).)*$|\" + loc.protocol + \"//\" + loc.host);\r\n        return url.match(reg);\r\n      }\r\n\r\n      // gather all resources\r\n      var scripts = document.getElementsByTagName(\"script\"),\r\n          links = document.getElementsByTagName(\"link\"),\r\n          uris = [];\r\n\r\n      // track local js urls\r\n      for (var i = 0; i < scripts.length; i++) {\r\n        var script = scripts[i], src = script.getAttribute(\"src\");\r\n        if (src && isLocal(src))\r\n          uris.push(src);\r\n        if (src && src.match(/\\blive.js#/)) {\r\n          for (var type in active)\r\n            active[type] = src.match(\"[#,|]\" + type) != null\r\n          if (src.match(\"notify\")) \r\n            alert(\"Live.js is loaded.\");\r\n        }\r\n      }\r\n      if (!active.js) uris = [];\r\n      if (active.html) uris.push(document.location.href);\r\n\r\n      // track local css urls\r\n      for (var i = 0; i < links.length && active.css; i++) {\r\n        var link = links[i], rel = link.getAttribute(\"rel\"), href = link.getAttribute(\"href\", 2);\r\n        if (href && rel && rel.match(new RegExp(\"stylesheet\", \"i\")) && isLocal(href)) {\r\n          uris.push(href);\r\n          currentLinkElements[href] = link;\r\n        }\r\n      }\r\n\r\n      // initialize the resources info\r\n      for (var i = 0; i < uris.length; i++) {\r\n        var url = uris[i];\r\n        Live.getHead(url, function (url, info) {\r\n          resources[url] = info;\r\n        });\r\n      }\r\n\r\n      // add rule for morphing between old and new css files\r\n      var head = document.getElementsByTagName(\"head\")[0],\r\n          style = document.createElement(\"style\"),\r\n          rule = \"transition: all .3s ease-out;\"\r\n      css = [\".livejs-loading * { \", rule, \" -webkit-\", rule, \"-moz-\", rule, \"-o-\", rule, \"}\"].join('');\r\n      style.setAttribute(\"type\", \"text/css\");\r\n      head.appendChild(style);\r\n      style.styleSheet ? style.styleSheet.cssText = css : style.appendChild(document.createTextNode(css));\r\n\r\n      // yep\r\n      loaded = true;\r\n    },\r\n\r\n    // check all tracking resources for changes\r\n    checkForChanges: function () {\r\n      for (var url in resources) {\r\n        if (pendingRequests[url])\r\n          continue;\r\n\r\n        Live.getHead(url, function (url, newInfo) {\r\n          var oldInfo = resources[url],\r\n              hasChanged = false;\r\n          resources[url] = newInfo;\r\n          for (var header in oldInfo) {\r\n            // do verification based on the header type\r\n            var oldValue = oldInfo[header],\r\n                newValue = newInfo[header],\r\n                contentType = newInfo[\"Content-Type\"];\r\n            switch (header.toLowerCase()) {\r\n              case \"etag\":\r\n                if (!newValue) break;\r\n                // fall through to default\r\n              default:\r\n                hasChanged = oldValue != newValue;\r\n                break;\r\n            }\r\n            // if changed, act\r\n            if (hasChanged) {\r\n              Live.refreshResource(url, contentType);\r\n              break;\r\n            }\r\n          }\r\n        });\r\n      }\r\n    },\r\n\r\n    // act upon a changed url of certain content type\r\n    refreshResource: function (url, type) {\r\n      switch (type.toLowerCase()) {\r\n        // css files can be reloaded dynamically by replacing the link element                               \r\n        case \"text/css\":\r\n          var link = currentLinkElements[url],\r\n              html = document.body.parentNode,\r\n              head = link.parentNode,\r\n              next = link.nextSibling,\r\n              newLink = document.createElement(\"link\");\r\n\r\n          html.className = html.className.replace(/\\s*livejs\\-loading/gi, '') + ' livejs-loading';\r\n          newLink.setAttribute(\"type\", \"text/css\");\r\n          newLink.setAttribute(\"rel\", \"stylesheet\");\r\n          newLink.setAttribute(\"href\", url + \"?now=\" + new Date() * 1);\r\n          next ? head.insertBefore(newLink, next) : head.appendChild(newLink);\r\n          currentLinkElements[url] = newLink;\r\n          oldLinkElements[url] = link;\r\n\r\n          // schedule removal of the old link\r\n          Live.removeoldLinkElements();\r\n          break;\r\n\r\n        // check if an html resource is our current url, then reload                               \r\n        case \"text/html\":\r\n          if (url != document.location.href)\r\n            return;\r\n\r\n          // local javascript changes cause a reload as well\r\n        case \"text/javascript\":\r\n        case \"application/javascript\":\r\n        case \"application/x-javascript\":\r\n          document.location.reload();\r\n      }\r\n    },\r\n\r\n    // removes the old stylesheet rules only once the new one has finished loading\r\n    removeoldLinkElements: function () {\r\n      var pending = 0;\r\n      for (var url in oldLinkElements) {\r\n        // if this sheet has any cssRules, delete the old link\r\n        try {\r\n          var link = currentLinkElements[url],\r\n              oldLink = oldLinkElements[url],\r\n              html = document.body.parentNode,\r\n              sheet = link.sheet || link.styleSheet,\r\n              rules = sheet.rules || sheet.cssRules;\r\n          if (rules.length >= 0) {\r\n            oldLink.parentNode.removeChild(oldLink);\r\n            delete oldLinkElements[url];\r\n            setTimeout(function () {\r\n              html.className = html.className.replace(/\\s*livejs\\-loading/gi, '');\r\n            }, 100);\r\n          }\r\n        } catch (e) {\r\n          pending++;\r\n        }\r\n        if (pending) setTimeout(Live.removeoldLinkElements, 50);\r\n      }\r\n    },\r\n\r\n    // performs a HEAD request and passes the header info to the given callback\r\n    getHead: function (url, callback) {\r\n      pendingRequests[url] = true;\r\n      var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject(\"Microsoft.XmlHttp\");\r\n      xhr.open(\"HEAD\", url, true);\r\n      xhr.onreadystatechange = function () {\r\n        delete pendingRequests[url];\r\n        if (xhr.readyState == 4 && xhr.status != 304) {\r\n          xhr.getAllResponseHeaders();\r\n          var info = {};\r\n          for (var h in headers) {\r\n            var value = xhr.getResponseHeader(h);\r\n            // adjust the simple Etag variant to match on its significant part\r\n            if (h.toLowerCase() == \"etag\" && value) value = value.replace(/^W\\//, '');\r\n            if (h.toLowerCase() == \"content-type\" && value) value = value.replace(/^(.*?);.*?$/i, \"$1\");\r\n            info[h] = value;\r\n          }\r\n          callback(url, info);\r\n        }\r\n      }\r\n      xhr.send();\r\n    }\r\n  };\r\n\r\n  // start listening\r\n  if (document.location.protocol != \"file:\") {\r\n    if (!window.liveJsLoaded)\r\n      Live.heartbeat();\r\n\r\n    window.liveJsLoaded = true;\r\n  }\r\n  else if (window.console)\r\n    console.log(\"Live.js doesn't support the file protocol. It needs http.\");    \r\n})();"
  },
  {
    "path": "docs/assets/js/menu-2.js",
    "content": "jQuery(document).ready(function($){\r\n\tvar $lateral_menu_trigger = $('.nav-trigger'),\r\n\t\t$content_wrapper = $('.main');\r\n\r\n\t//open-close lateral menu clicking on the menu icon\r\n\t$lateral_menu_trigger.on('click', function(event){\r\n\t\tevent.preventDefault();\r\n\r\n\t\t$lateral_menu_trigger.toggleClass('is-open');\r\n\t\t$content_wrapper.toggleClass('is-open').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){\r\n\t\t\t// firefox transitions break when parent overflow is changed, so we need to wait for the end of the trasition to give the body an overflow hidden\r\n\t\t\t$('body').toggleClass('overflow-hidden');\r\n\t\t});\r\n\t\t$('.menu-inner').toggleClass('is-open');\r\n\r\n\t\t//check if transitions are not supported - i.e. in IE9\r\n\t\tif($('html').hasClass('no-csstransitions')) {\r\n\t\t\t$('body').toggleClass('overflow-hidden');\r\n\t\t}\r\n\t});\r\n\r\n\t//close lateral menu clicking outside the menu itself\r\n\t$content_wrapper.on('mouseover', function(event){\r\n\t\tif( !$(event.target).is('.nav-trigger, .nav-trigger span') ) {\r\n\t\t\t$lateral_menu_trigger.removeClass('is-open');\r\n\t\t\t$content_wrapper.removeClass('is-open').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){\r\n\t\t\t\t$('body').removeClass('overflow-hidden');\r\n\t\t\t});\r\n\t\t\t$('.menu-inner').removeClass('is-open');\r\n\t\t\t//check if transitions are not supported\r\n\t\t\tif($('html').hasClass('no-csstransitions')) {\r\n\t\t\t\t$('body').removeClass('overflow-hidden');\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t});\r\n});\r\n"
  },
  {
    "path": "docs/assets/js/menu.js",
    "content": "/* ---- Menu Section For Fold Personal Portfolio HTML Template --- */\r\n\r\njQuery(document).ready(function($){\r\n\tvar $lateral_menu_trigger = $('.nav-trigger'),\r\n\t\t$content_wrapper = $('.main');\r\n\r\n\t//open-close lateral menu clicking on the menu icon\r\n\t$lateral_menu_trigger.on('click', function(event){\r\n\t\tevent.preventDefault();\r\n\r\n\t\t$lateral_menu_trigger.toggleClass('is-active');\r\n\t\t$content_wrapper.toggleClass('is-active').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){\r\n\t\t\t// firefox transitions break when parent overflow is changed, so we need to wait for the end of the trasition to give the body an overflow hidden\r\n\t\t\t$('body').toggleClass('overflow-hidden');\r\n\t\t});\r\n\t\t$('#fld-nav').toggleClass('is-active');\r\n\r\n\t\t//check if transitions are not supported - i.e. in IE9\r\n\t\tif($('html').hasClass('no-csstransitions')) {\r\n\t\t\t$('body').toggleClass('overflow-hidden');\r\n\t\t}\r\n\t});\r\n\r\n\t//close lateral menu clicking outside the menu itself\r\n\t$content_wrapper.on('mouseover', function(event){\r\n\t\tif( !$(event.target).is('.nav-trigger, .nav-trigger span') ) {\r\n\t\t\t$lateral_menu_trigger.removeClass('is-active');\r\n\t\t\t$content_wrapper.removeClass('is-active').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){\r\n\t\t\t\t$('body').removeClass('overflow-hidden');\r\n\t\t\t});\r\n\t\t\t$('#fld-nav').removeClass('is-active');\r\n\t\t\t//check if transitions are not supported\r\n\t\t\tif($('html').hasClass('no-csstransitions')) {\r\n\t\t\t\t$('body').removeClass('overflow-hidden');\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t});\r\n});\r\n"
  },
  {
    "path": "docs/assets/js/plugins.js",
    "content": "﻿/* jQuery Plugins and Scripts*/\r\n/* Animisition\r\nJarallax\r\nSmoothScroll\r\nOwl Carousel\r\nImagesloaded\r\nIsotope JS\r\nWow Js\r\nCounter Up\r\nWayPoints\r\n*/\r\n\r\n/*!\n * animsition v4.0.2\n * A simple and easy jQuery plugin for CSS animated page transitions.\n \r\n* http://blivesta.github.io/animsition\n * License : MIT\n * Author : blivesta (http://blivesta.com/)\n */\n\r\n\r\n!function(t){\"use strict\";\"function\"==typeof define&&define.amd?define([\"jquery\"],t):\"object\"==typeof exports?module.exports=t(require(\"jquery\")):t(jQuery)}(function(t){\"use strict\";var n=\"animsition\",i={init:function(a){a=t.extend({inClass:\"fade-in\",outClass:\"fade-out\",inDuration:1500,outDuration:800,linkElement:\".animsition-link\",loading:!0,loadingParentElement:\"body\",loadingClass:\"animsition-loading\",loadingInner:\"\",timeout:!1,timeoutCountdown:5e3,onLoadEvent:!0,browser:[\"animation-duration\",\"-webkit-animation-duration\"],overlay:!1,overlayClass:\"animsition-overlay-slide\",overlayParentElement:\"body\",transition:function(t){window.location.href=t}},a),i.settings={timer:!1,data:{inClass:\"animsition-in-class\",inDuration:\"animsition-in-duration\",outClass:\"animsition-out-class\",outDuration:\"animsition-out-duration\",overlay:\"animsition-overlay\"},events:{inStart:\"animsition.inStart\",inEnd:\"animsition.inEnd\",outStart:\"animsition.outStart\",outEnd:\"animsition.outEnd\"}};var o=i.supportCheck.call(this,a);if(!o&&a.browser.length>0&&(!o||!this.length))return\"console\"in window||(window.console={},window.console.log=function(t){return t}),this.length||console.log(\"Animsition: Element does not exist on page.\"),o||console.log(\"Animsition: Does not support this browser.\"),i.destroy.call(this);var e=i.optionCheck.call(this,a);return e&&t(\".\"+a.overlayClass).length<=0&&i.addOverlay.call(this,a),a.loading&&t(\".\"+a.loadingClass).length<=0&&i.addLoading.call(this,a),this.each(function(){var o=this,e=t(this),s=t(window),r=t(document),l=e.data(n);l||(a=t.extend({},a),e.data(n,{options:a}),a.timeout&&i.addTimer.call(o),a.onLoadEvent&&s.on(\"load.\"+n,function(){i.settings.timer&&clearTimeout(i.settings.timer),i[\"in\"].call(o)}),s.on(\"pageshow.\"+n,function(t){t.originalEvent.persisted&&i[\"in\"].call(o)}),s.on(\"unload.\"+n,function(){}),r.on(\"click.\"+n,a.linkElement,function(n){n.preventDefault();var a=t(this),e=a.attr(\"href\");2===n.which||n.metaKey||n.shiftKey||-1!==navigator.platform.toUpperCase().indexOf(\"WIN\")&&n.ctrlKey?window.open(e,\"_blank\"):i.out.call(o,a,e)}))})},addOverlay:function(n){t(n.overlayParentElement).prepend('<div class=\"'+n.overlayClass+'\"></div>')},addLoading:function(n){t(n.loadingParentElement).append('<div class=\"'+n.loadingClass+'\">'+n.loadingInner+\"</div>\")},removeLoading:function(){var i=t(this),a=i.data(n).options,o=t(a.loadingParentElement).children(\".\"+a.loadingClass);o.fadeOut().remove()},addTimer:function(){var a=this,o=t(this),e=o.data(n).options;i.settings.timer=setTimeout(function(){i[\"in\"].call(a),t(window).off(\"load.\"+n)},e.timeoutCountdown)},supportCheck:function(n){var i=t(this),a=n.browser,o=a.length,e=!1;0===o&&(e=!0);for(var s=0;o>s;s++)if(\"string\"==typeof i.css(a[s])){e=!0;break}return e},optionCheck:function(n){var a,o=t(this);return a=n.overlay||o.data(i.settings.data.overlay)?!0:!1},animationCheck:function(i,a,o){var e=t(this),s=e.data(n).options,r=typeof i,l=!a&&\"number\"===r,d=a&&\"string\"===r&&i.length>0;return l||d?i=i:a&&o?i=s.inClass:!a&&o?i=s.inDuration:a&&!o?i=s.outClass:a||o||(i=s.outDuration),i},\"in\":function(){var a=this,o=t(this),e=o.data(n).options,s=o.data(i.settings.data.inDuration),r=o.data(i.settings.data.inClass),l=i.animationCheck.call(a,s,!1,!0),d=i.animationCheck.call(a,r,!0,!0),u=i.optionCheck.call(a,e),c=o.data(n).outClass;e.loading&&i.removeLoading.call(a),c&&o.removeClass(c),u?i.inOverlay.call(a,d,l):i.inDefault.call(a,d,l)},inDefault:function(n,a){var o=t(this);o.css({\"animation-duration\":a+\"ms\"}).addClass(n).trigger(i.settings.events.inStart).animateCallback(function(){o.removeClass(n).css({opacity:1}).trigger(i.settings.events.inEnd)})},inOverlay:function(a,o){var e=t(this),s=e.data(n).options;e.css({opacity:1}).trigger(i.settings.events.inStart),t(s.overlayParentElement).children(\".\"+s.overlayClass).css({\"animation-duration\":o+\"ms\"}).addClass(a).animateCallback(function(){e.trigger(i.settings.events.inEnd)})},out:function(a,o){var e=this,s=t(this),r=s.data(n).options,l=a.data(i.settings.data.outClass),d=s.data(i.settings.data.outClass),u=a.data(i.settings.data.outDuration),c=s.data(i.settings.data.outDuration),m=l?l:d,g=u?u:c,f=i.animationCheck.call(e,m,!0,!1),v=i.animationCheck.call(e,g,!1,!1),h=i.optionCheck.call(e,r);s.data(n).outClass=f,h?i.outOverlay.call(e,f,v,o):i.outDefault.call(e,f,v,o)},outDefault:function(a,o,e){var s=t(this),r=s.data(n).options;s.css({\"animation-duration\":o+1+\"ms\"}).addClass(a).trigger(i.settings.events.outStart).animateCallback(function(){s.trigger(i.settings.events.outEnd),r.transition(e)})},outOverlay:function(a,o,e){var s=this,r=t(this),l=r.data(n).options,d=r.data(i.settings.data.inClass),u=i.animationCheck.call(s,d,!0,!0);t(l.overlayParentElement).children(\".\"+l.overlayClass).css({\"animation-duration\":o+1+\"ms\"}).removeClass(u).addClass(a).trigger(i.settings.events.outStart).animateCallback(function(){r.trigger(i.settings.events.outEnd),l.transition(e)})},destroy:function(){return this.each(function(){var i=t(this);t(window).off(\".\"+n),i.css({opacity:1}).removeData(n)})}};t.fn.animateCallback=function(n){var i=\"animationend webkitAnimationEnd\";return this.each(function(){var a=t(this);a.on(i,function(){return a.off(i),n.call(this)})})},t.fn.animsition=function(a){return i[a]?i[a].apply(this,Array.prototype.slice.call(arguments,1)):\"object\"!=typeof a&&a?void t.error(\"Method \"+a+\" does not exist on jQuery.\"+n):i.init.apply(this,arguments)}});\r\n\r\n\r\n//\r\n// SmoothScroll for websites v1.4.9 (Balazs Galambosi)\r\n// http://www.smoothscroll.net/\r\n//\r\n// Licensed under the terms of the MIT license.\r\n//\r\n// You may use it in your theme if you credit me. \r\n// It is also free to use on any individual website.\r\n//\r\n// Exception:\r\n// The only restriction is to not publish any  \r\n// extension for browsers or native application\r\n// without getting a written permission first.\r\n//\r\n\r\n(function () {\r\n  \r\n// Scroll Variables (tweakable)\r\nvar defaultOptions = {\r\n\r\n    // Scrolling Core\r\n    frameRate        : 150, // [Hz]\r\n    animationTime    : 400, // [ms]\r\n    stepSize         : 100, // [px]\r\n\r\n    // Pulse (less tweakable)\r\n    // ratio of \"tail\" to \"acceleration\"\r\n    pulseAlgorithm   : true,\r\n    pulseScale       : 4,\r\n    pulseNormalize   : 1,\r\n\r\n    // Acceleration\r\n    accelerationDelta : 50,  // 50\r\n    accelerationMax   : 3,   // 3\r\n\r\n    // Keyboard Settings\r\n    keyboardSupport   : true,  // option\r\n    arrowScroll       : 50,    // [px]\r\n\r\n    // Other\r\n    fixedBackground   : true, \r\n    excluded          : ''    \r\n};\r\n\r\nvar options = defaultOptions;\r\n\r\n\r\n// Other Variables\r\nvar isExcluded = false;\r\nvar isFrame = false;\r\nvar direction = { x: 0, y: 0 };\r\nvar initDone  = false;\r\nvar root = document.documentElement;\r\nvar activeElement;\r\nvar observer;\r\nvar refreshSize;\r\nvar deltaBuffer = [];\r\nvar deltaBufferTimer;\r\nvar isMac = /^Mac/.test(navigator.platform);\r\n\r\nvar key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32, \r\n            pageup: 33, pagedown: 34, end: 35, home: 36 };\r\nvar arrowKeys = { 37: 1, 38: 1, 39: 1, 40: 1 };\r\n\r\n/***********************************************\r\n * INITIALIZE\r\n ***********************************************/\r\n\r\n/**\r\n * Tests if smooth scrolling is allowed. Shuts down everything if not.\r\n */\r\nfunction initTest() {\r\n    if (options.keyboardSupport) {\r\n        addEvent('keydown', keydown);\r\n    }\r\n}\r\n\r\n/**\r\n * Sets up scrolls array, determines if frames are involved.\r\n */\r\nfunction init() {\r\n  \r\n    if (initDone || !document.body) return;\r\n\r\n    initDone = true;\r\n\r\n    var body = document.body;\r\n    var html = document.documentElement;\r\n    var windowHeight = window.innerHeight; \r\n    var scrollHeight = body.scrollHeight;\r\n    \r\n    // check compat mode for root element\r\n    root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;\r\n    activeElement = body;\r\n    \r\n    initTest();\r\n\r\n    // Checks if this script is running in a frame\r\n    if (top != self) {\r\n        isFrame = true;\r\n    }\r\n\r\n    /**\r\n     * Safari 10 fixed it, Chrome fixed it in v45:\r\n     * This fixes a bug where the areas left and right to \r\n     * the content does not trigger the onmousewheel event\r\n     * on some pages. e.g.: html, body { height: 100% }\r\n     */\r\n    else if (isOldSafari &&\r\n             scrollHeight > windowHeight &&\r\n            (body.offsetHeight <= windowHeight || \r\n             html.offsetHeight <= windowHeight)) {\r\n\r\n        var fullPageElem = document.createElement('div');\r\n        fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' +\r\n                                     'top:0; left:0; right:0; height:' + \r\n                                      root.scrollHeight + 'px';\r\n        document.body.appendChild(fullPageElem);\r\n        \r\n        // DOM changed (throttled) to fix height\r\n        var pendingRefresh;\r\n        refreshSize = function () {\r\n            if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh);\r\n            pendingRefresh = setTimeout(function () {\r\n                if (isExcluded) return; // could be running after cleanup\r\n                fullPageElem.style.height = '0';\r\n                fullPageElem.style.height = root.scrollHeight + 'px';\r\n                pendingRefresh = null;\r\n            }, 500); // act rarely to stay fast\r\n        };\r\n  \r\n        setTimeout(refreshSize, 10);\r\n\r\n        addEvent('resize', refreshSize);\r\n\r\n        // TODO: attributeFilter?\r\n        var config = {\r\n            attributes: true, \r\n            childList: true, \r\n            characterData: false \r\n            // subtree: true\r\n        };\r\n\r\n        observer = new MutationObserver(refreshSize);\r\n        observer.observe(body, config);\r\n\r\n        if (root.offsetHeight <= windowHeight) {\r\n            var clearfix = document.createElement('div');   \r\n            clearfix.style.clear = 'both';\r\n            body.appendChild(clearfix);\r\n        }\r\n    }\r\n\r\n    // disable fixed background\r\n    if (!options.fixedBackground && !isExcluded) {\r\n        body.style.backgroundAttachment = 'scroll';\r\n        html.style.backgroundAttachment = 'scroll';\r\n    }\r\n}\r\n\r\n/**\r\n * Removes event listeners and other traces left on the page.\r\n */\r\nfunction cleanup() {\r\n    observer && observer.disconnect();\r\n    removeEvent(wheelEvent, wheel);\r\n    removeEvent('mousedown', mousedown);\r\n    removeEvent('keydown', keydown);\r\n    removeEvent('resize', refreshSize);\r\n    removeEvent('load', init);\r\n}\r\n\r\n\r\n/************************************************\r\n * SCROLLING \r\n ************************************************/\r\n \r\nvar que = [];\r\nvar pending = false;\r\nvar lastScroll = Date.now();\r\n\r\n/**\r\n * Pushes scroll actions to the scrolling queue.\r\n */\r\nfunction scrollArray(elem, left, top) {\r\n    \r\n    directionCheck(left, top);\r\n\r\n    if (options.accelerationMax != 1) {\r\n        var now = Date.now();\r\n        var elapsed = now - lastScroll;\r\n        if (elapsed < options.accelerationDelta) {\r\n            var factor = (1 + (50 / elapsed)) / 2;\r\n            if (factor > 1) {\r\n                factor = Math.min(factor, options.accelerationMax);\r\n                left *= factor;\r\n                top  *= factor;\r\n            }\r\n        }\r\n        lastScroll = Date.now();\r\n    }          \r\n    \r\n    // push a scroll command\r\n    que.push({\r\n        x: left, \r\n        y: top, \r\n        lastX: (left < 0) ? 0.99 : -0.99,\r\n        lastY: (top  < 0) ? 0.99 : -0.99, \r\n        start: Date.now()\r\n    });\r\n        \r\n    // don't act if there's a pending queue\r\n    if (pending) {\r\n        return;\r\n    }  \r\n\r\n    var scrollRoot = getScrollRoot();\r\n    var isWindowScroll = (elem === scrollRoot || elem === document.body);\r\n    \r\n    // if we haven't already fixed the behavior, \r\n    // and it needs fixing for this sesh\r\n    if (elem.$scrollBehavior == null && isScrollBehaviorSmooth(elem)) {\r\n        elem.$scrollBehavior = elem.style.scrollBehavior;\r\n        elem.style.scrollBehavior = 'auto';\r\n    }\r\n\r\n    var step = function (time) {\r\n        \r\n        var now = Date.now();\r\n        var scrollX = 0;\r\n        var scrollY = 0; \r\n    \r\n        for (var i = 0; i < que.length; i++) {\r\n            \r\n            var item = que[i];\r\n            var elapsed  = now - item.start;\r\n            var finished = (elapsed >= options.animationTime);\r\n            \r\n            // scroll position: [0, 1]\r\n            var position = (finished) ? 1 : elapsed / options.animationTime;\r\n            \r\n            // easing [optional]\r\n            if (options.pulseAlgorithm) {\r\n                position = pulse(position);\r\n            }\r\n            \r\n            // only need the difference\r\n            var x = (item.x * position - item.lastX) >> 0;\r\n            var y = (item.y * position - item.lastY) >> 0;\r\n            \r\n            // add this to the total scrolling\r\n            scrollX += x;\r\n            scrollY += y;            \r\n            \r\n            // update last values\r\n            item.lastX += x;\r\n            item.lastY += y;\r\n        \r\n            // delete and step back if it's over\r\n            if (finished) {\r\n                que.splice(i, 1); i--;\r\n            }           \r\n        }\r\n\r\n        // scroll left and top\r\n        if (isWindowScroll) {\r\n            window.scrollBy(scrollX, scrollY);\r\n        } \r\n        else {\r\n            if (scrollX) elem.scrollLeft += scrollX;\r\n            if (scrollY) elem.scrollTop  += scrollY;                    \r\n        }\r\n        \r\n        // clean up if there's nothing left to do\r\n        if (!left && !top) {\r\n            que = [];\r\n        }\r\n        \r\n        if (que.length) { \r\n            requestFrame(step, elem, (1000 / options.frameRate + 1)); \r\n        } else { \r\n            pending = false;\r\n            // restore default behavior at the end of scrolling sesh\r\n            if (elem.$scrollBehavior != null) {\r\n                elem.style.scrollBehavior = elem.$scrollBehavior;\r\n                elem.$scrollBehavior = null;\r\n            }\r\n        }\r\n    };\r\n    \r\n    // start a new queue of actions\r\n    requestFrame(step, elem, 0);\r\n    pending = true;\r\n}\r\n\r\n\r\n/***********************************************\r\n * EVENTS\r\n ***********************************************/\r\n\r\n/**\r\n * Mouse wheel handler.\r\n * @param {Object} event\r\n */\r\nfunction wheel(event) {\r\n\r\n    if (!initDone) {\r\n        init();\r\n    }\r\n    \r\n    var target = event.target;\r\n\r\n    // leave early if default action is prevented   \r\n    // or it's a zooming event with CTRL \r\n    if (event.defaultPrevented || event.ctrlKey) {\r\n        return true;\r\n    }\r\n    \r\n    // leave embedded content alone (flash & pdf)\r\n    if (isNodeName(activeElement, 'embed') || \r\n       (isNodeName(target, 'embed') && /\\.pdf/i.test(target.src)) ||\r\n        isNodeName(activeElement, 'object') ||\r\n        target.shadowRoot) {\r\n        return true;\r\n    }\r\n\r\n    var deltaX = -event.wheelDeltaX || event.deltaX || 0;\r\n    var deltaY = -event.wheelDeltaY || event.deltaY || 0;\r\n    \r\n    if (isMac) {\r\n        if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {\r\n            deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));\r\n        }\r\n        if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {\r\n            deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));\r\n        }\r\n    }\r\n    \r\n    // use wheelDelta if deltaX/Y is not available\r\n    if (!deltaX && !deltaY) {\r\n        deltaY = -event.wheelDelta || 0;\r\n    }\r\n\r\n    // line based scrolling (Firefox mostly)\r\n    if (event.deltaMode === 1) {\r\n        deltaX *= 40;\r\n        deltaY *= 40;\r\n    }\r\n\r\n    var overflowing = overflowingAncestor(target);\r\n\r\n    // nothing to do if there's no element that's scrollable\r\n    if (!overflowing) {\r\n        // except Chrome iframes seem to eat wheel events, which we need to \r\n        // propagate up, if the iframe has nothing overflowing to scroll\r\n        if (isFrame && isChrome)  {\r\n            // change target to iframe element itself for the parent frame\r\n            Object.defineProperty(event, \"target\", {value: window.frameElement});\r\n            return parent.wheel(event);\r\n        }\r\n        return true;\r\n    }\r\n    \r\n    // check if it's a touchpad scroll that should be ignored\r\n    if (isTouchpad(deltaY)) {\r\n        return true;\r\n    }\r\n\r\n    // scale by step size\r\n    // delta is 120 most of the time\r\n    // synaptics seems to send 1 sometimes\r\n    if (Math.abs(deltaX) > 1.2) {\r\n        deltaX *= options.stepSize / 120;\r\n    }\r\n    if (Math.abs(deltaY) > 1.2) {\r\n        deltaY *= options.stepSize / 120;\r\n    }\r\n    \r\n    scrollArray(overflowing, deltaX, deltaY);\r\n    event.preventDefault();\r\n    scheduleClearCache();\r\n}\r\n\r\n/**\r\n * Keydown event handler.\r\n * @param {Object} event\r\n */\r\nfunction keydown(event) {\r\n\r\n    var target   = event.target;\r\n    var modifier = event.ctrlKey || event.altKey || event.metaKey || \r\n                  (event.shiftKey && event.keyCode !== key.spacebar);\r\n    \r\n    // our own tracked active element could've been removed from the DOM\r\n    if (!document.body.contains(activeElement)) {\r\n        activeElement = document.activeElement;\r\n    }\r\n\r\n    // do nothing if user is editing text\r\n    // or using a modifier key (except shift)\r\n    // or in a dropdown\r\n    // or inside interactive elements\r\n    var inputNodeNames = /^(textarea|select|embed|object)$/i;\r\n    var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;\r\n    if ( event.defaultPrevented ||\r\n         inputNodeNames.test(target.nodeName) ||\r\n         isNodeName(target, 'input') && !buttonTypes.test(target.type) ||\r\n         isNodeName(activeElement, 'video') ||\r\n         isInsideYoutubeVideo(event) ||\r\n         target.isContentEditable || \r\n         modifier ) {\r\n      return true;\r\n    }\r\n\r\n    // [spacebar] should trigger button press, leave it alone\r\n    if ((isNodeName(target, 'button') ||\r\n         isNodeName(target, 'input') && buttonTypes.test(target.type)) &&\r\n        event.keyCode === key.spacebar) {\r\n      return true;\r\n    }\r\n\r\n    // [arrwow keys] on radio buttons should be left alone\r\n    if (isNodeName(target, 'input') && target.type == 'radio' &&\r\n        arrowKeys[event.keyCode])  {\r\n      return true;\r\n    }\r\n    \r\n    var shift, x = 0, y = 0;\r\n    var overflowing = overflowingAncestor(activeElement);\r\n\r\n    if (!overflowing) {\r\n        // Chrome iframes seem to eat key events, which we need to \r\n        // propagate up, if the iframe has nothing overflowing to scroll\r\n        return (isFrame && isChrome) ? parent.keydown(event) : true;\r\n    }\r\n\r\n    var clientHeight = overflowing.clientHeight; \r\n\r\n    if (overflowing == document.body) {\r\n        clientHeight = window.innerHeight;\r\n    }\r\n\r\n    switch (event.keyCode) {\r\n        case key.up:\r\n            y = -options.arrowScroll;\r\n            break;\r\n        case key.down:\r\n            y = options.arrowScroll;\r\n            break;         \r\n        case key.spacebar: // (+ shift)\r\n            shift = event.shiftKey ? 1 : -1;\r\n            y = -shift * clientHeight * 0.9;\r\n            break;\r\n        case key.pageup:\r\n            y = -clientHeight * 0.9;\r\n            break;\r\n        case key.pagedown:\r\n            y = clientHeight * 0.9;\r\n            break;\r\n        case key.home:\r\n            if (overflowing == document.body && document.scrollingElement)\r\n                overflowing = document.scrollingElement;\r\n            y = -overflowing.scrollTop;\r\n            break;\r\n        case key.end:\r\n            var scroll = overflowing.scrollHeight - overflowing.scrollTop;\r\n            var scrollRemaining = scroll - clientHeight;\r\n            y = (scrollRemaining > 0) ? scrollRemaining + 10 : 0;\r\n            break;\r\n        case key.left:\r\n            x = -options.arrowScroll;\r\n            break;\r\n        case key.right:\r\n            x = options.arrowScroll;\r\n            break;            \r\n        default:\r\n            return true; // a key we don't care about\r\n    }\r\n\r\n    scrollArray(overflowing, x, y);\r\n    event.preventDefault();\r\n    scheduleClearCache();\r\n}\r\n\r\n/**\r\n * Mousedown event only for updating activeElement\r\n */\r\nfunction mousedown(event) {\r\n    activeElement = event.target;\r\n}\r\n\r\n\r\n/***********************************************\r\n * OVERFLOW\r\n ***********************************************/\r\n\r\nvar uniqueID = (function () {\r\n    var i = 0;\r\n    return function (el) {\r\n        return el.uniqueID || (el.uniqueID = i++);\r\n    };\r\n})();\r\n\r\nvar cacheX = {}; // cleared out after a scrolling session\r\nvar cacheY = {}; // cleared out after a scrolling session\r\nvar clearCacheTimer;\r\nvar smoothBehaviorForElement = {};\r\n\r\n//setInterval(function () { cache = {}; }, 10 * 1000);\r\n\r\nfunction scheduleClearCache() {\r\n    clearTimeout(clearCacheTimer);\r\n    clearCacheTimer = setInterval(function () { \r\n        cacheX = cacheY = smoothBehaviorForElement = {}; \r\n    }, 1*1000);\r\n}\r\n\r\nfunction setCache(elems, overflowing, x) {\r\n    var cache = x ? cacheX : cacheY;\r\n    for (var i = elems.length; i--;)\r\n        cache[uniqueID(elems[i])] = overflowing;\r\n    return overflowing;\r\n}\r\n\r\nfunction getCache(el, x) {\r\n    return (x ? cacheX : cacheY)[uniqueID(el)];\r\n}\r\n\r\n//  (body)                (root)\r\n//         | hidden | visible | scroll |  auto  |\r\n// hidden  |   no   |    no   |   YES  |   YES  |\r\n// visible |   no   |   YES   |   YES  |   YES  |\r\n// scroll  |   no   |   YES   |   YES  |   YES  |\r\n// auto    |   no   |   YES   |   YES  |   YES  |\r\n\r\nfunction overflowingAncestor(el) {\r\n    var elems = [];\r\n    var body = document.body;\r\n    var rootScrollHeight = root.scrollHeight;\r\n    do {\r\n        var cached = getCache(el, false);\r\n        if (cached) {\r\n            return setCache(elems, cached);\r\n        }\r\n        elems.push(el);\r\n        if (rootScrollHeight === el.scrollHeight) {\r\n            var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);\r\n            var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);\r\n            if (isFrame && isContentOverflowing(root) || \r\n               !isFrame && isOverflowCSS) {\r\n                return setCache(elems, getScrollRoot()); \r\n            }\r\n        } else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {\r\n            return setCache(elems, el);\r\n        }\r\n    } while ((el = el.parentElement));\r\n}\r\n\r\nfunction isContentOverflowing(el) {\r\n    return (el.clientHeight + 10 < el.scrollHeight);\r\n}\r\n\r\n// typically for <body> and <html>\r\nfunction overflowNotHidden(el) {\r\n    var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');\r\n    return (overflow !== 'hidden');\r\n}\r\n\r\n// for all other elements\r\nfunction overflowAutoOrScroll(el) {\r\n    var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');\r\n    return (overflow === 'scroll' || overflow === 'auto');\r\n}\r\n\r\n// for all other elements\r\nfunction isScrollBehaviorSmooth(el) {\r\n    var id = uniqueID(el);\r\n    if (smoothBehaviorForElement[id] == null) {\r\n        var scrollBehavior = getComputedStyle(el, '')['scroll-behavior'];\r\n        smoothBehaviorForElement[id] = ('smooth' == scrollBehavior);\r\n    }\r\n    return smoothBehaviorForElement[id];\r\n}\r\n\r\n\r\n/***********************************************\r\n * HELPERS\r\n ***********************************************/\r\n\r\nfunction addEvent(type, fn, arg) {\r\n    window.addEventListener(type, fn, arg || false);\r\n}\r\n\r\nfunction removeEvent(type, fn, arg) {\r\n    window.removeEventListener(type, fn, arg || false);  \r\n}\r\n\r\nfunction isNodeName(el, tag) {\r\n    return el && (el.nodeName||'').toLowerCase() === tag.toLowerCase();\r\n}\r\n\r\nfunction directionCheck(x, y) {\r\n    x = (x > 0) ? 1 : -1;\r\n    y = (y > 0) ? 1 : -1;\r\n    if (direction.x !== x || direction.y !== y) {\r\n        direction.x = x;\r\n        direction.y = y;\r\n        que = [];\r\n        lastScroll = 0;\r\n    }\r\n}\r\n\r\nif (window.localStorage && localStorage.SS_deltaBuffer) {\r\n    try { // #46 Safari throws in private browsing for localStorage \r\n        deltaBuffer = localStorage.SS_deltaBuffer.split(',');\r\n    } catch (e) { } \r\n}\r\n\r\nfunction isTouchpad(deltaY) {\r\n    if (!deltaY) return;\r\n    if (!deltaBuffer.length) {\r\n        deltaBuffer = [deltaY, deltaY, deltaY];\r\n    }\r\n    deltaY = Math.abs(deltaY);\r\n    deltaBuffer.push(deltaY);\r\n    deltaBuffer.shift();\r\n    clearTimeout(deltaBufferTimer);\r\n    deltaBufferTimer = setTimeout(function () {\r\n        try { // #46 Safari throws in private browsing for localStorage\r\n            localStorage.SS_deltaBuffer = deltaBuffer.join(',');\r\n        } catch (e) { }  \r\n    }, 1000);\r\n    var dpiScaledWheelDelta = deltaY > 120 && allDeltasDivisableBy(deltaY); // win64 \r\n    return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100) && !dpiScaledWheelDelta;\r\n} \r\n\r\nfunction isDivisible(n, divisor) {\r\n    return (Math.floor(n / divisor) == n / divisor);\r\n}\r\n\r\nfunction allDeltasDivisableBy(divisor) {\r\n    return (isDivisible(deltaBuffer[0], divisor) &&\r\n            isDivisible(deltaBuffer[1], divisor) &&\r\n            isDivisible(deltaBuffer[2], divisor));\r\n}\r\n\r\nfunction isInsideYoutubeVideo(event) {\r\n    var elem = event.target;\r\n    var isControl = false;\r\n    if (document.URL.indexOf ('www.youtube.com/watch') != -1) {\r\n        do {\r\n            isControl = (elem.classList && \r\n                         elem.classList.contains('html5-video-controls'));\r\n            if (isControl) break;\r\n        } while ((elem = elem.parentNode));\r\n    }\r\n    return isControl;\r\n}\r\n\r\nvar requestFrame = (function () {\r\n      return (window.requestAnimationFrame       || \r\n              window.webkitRequestAnimationFrame || \r\n              window.mozRequestAnimationFrame    ||\r\n              function (callback, element, delay) {\r\n                 window.setTimeout(callback, delay || (1000/60));\r\n             });\r\n})();\r\n\r\nvar MutationObserver = (window.MutationObserver || \r\n                        window.WebKitMutationObserver ||\r\n                        window.MozMutationObserver);  \r\n\r\nvar getScrollRoot = (function() {\r\n  var SCROLL_ROOT = document.scrollingElement;\r\n  return function() {\r\n    if (!SCROLL_ROOT) {\r\n      var dummy = document.createElement('div');\r\n      dummy.style.cssText = 'height:10000px;width:1px;';\r\n      document.body.appendChild(dummy);\r\n      var bodyScrollTop  = document.body.scrollTop;\r\n      var docElScrollTop = document.documentElement.scrollTop;\r\n      window.scrollBy(0, 3);\r\n      if (document.body.scrollTop != bodyScrollTop)\r\n        (SCROLL_ROOT = document.body);\r\n      else \r\n        (SCROLL_ROOT = document.documentElement);\r\n      window.scrollBy(0, -3);\r\n      document.body.removeChild(dummy);\r\n    }\r\n    return SCROLL_ROOT;\r\n  };\r\n})();\r\n\r\n\r\n/***********************************************\r\n * PULSE (by Michael Herf)\r\n ***********************************************/\r\n \r\n/**\r\n * Viscous fluid with a pulse for part and decay for the rest.\r\n * - Applies a fixed force over an interval (a damped acceleration), and\r\n * - Lets the exponential bleed away the velocity over a longer interval\r\n * - Michael Herf, http://stereopsis.com/stopping/\r\n */\r\nfunction pulse_(x) {\r\n    var val, start, expx;\r\n    // test\r\n    x = x * options.pulseScale;\r\n    if (x < 1) { // acceleartion\r\n        val = x - (1 - Math.exp(-x));\r\n    } else {     // tail\r\n        // the previous animation ended here:\r\n        start = Math.exp(-1);\r\n        // simple viscous drag\r\n        x -= 1;\r\n        expx = 1 - Math.exp(-x);\r\n        val = start + (expx * (1 - start));\r\n    }\r\n    return val * options.pulseNormalize;\r\n}\r\n\r\nfunction pulse(x) {\r\n    if (x >= 1) return 1;\r\n    if (x <= 0) return 0;\r\n\r\n    if (options.pulseNormalize == 1) {\r\n        options.pulseNormalize /= pulse_(1);\r\n    }\r\n    return pulse_(x);\r\n}\r\n\r\n\r\n/***********************************************\r\n * FIRST RUN\r\n ***********************************************/\r\n\r\nvar userAgent = window.navigator.userAgent;\r\nvar isEdge    = /Edge/.test(userAgent); // thank you MS\r\nvar isChrome  = /chrome/i.test(userAgent) && !isEdge; \r\nvar isSafari  = /safari/i.test(userAgent) && !isEdge; \r\nvar isMobile  = /mobile/i.test(userAgent);\r\nvar isIEWin7  = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent);\r\nvar isOldSafari = isSafari && (/Version\\/8/i.test(userAgent) || /Version\\/9/i.test(userAgent));\r\nvar isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile;\r\n\r\nvar supportsPassive = false;\r\ntry {\r\n  window.addEventListener(\"test\", null, Object.defineProperty({}, 'passive', {\r\n    get: function () {\r\n            supportsPassive = true;\r\n        } \r\n    }));\r\n} catch(e) {}\r\n\r\nvar wheelOpt = supportsPassive ? { passive: false } : false;\r\nvar wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel'; \r\n\r\nif (wheelEvent && isEnabledForBrowser) {\r\n    addEvent(wheelEvent, wheel, wheelOpt);\r\n    addEvent('mousedown', mousedown);\r\n    addEvent('load', init);\r\n}\r\n\r\n\r\n/***********************************************\r\n * PUBLIC INTERFACE\r\n ***********************************************/\r\n\r\nfunction SmoothScroll(optionsToSet) {\r\n    for (var key in optionsToSet)\r\n        if (defaultOptions.hasOwnProperty(key)) \r\n            options[key] = optionsToSet[key];\r\n}\r\nSmoothScroll.destroy = cleanup;\r\n\r\nif (window.SmoothScrollOptions) // async API\r\n    SmoothScroll(window.SmoothScrollOptions);\r\n\r\nif (typeof define === 'function' && define.amd)\r\n    define(function() {\r\n        return SmoothScroll;\r\n    });\r\nelse if ('object' == typeof exports)\r\n    module.exports = SmoothScroll;\r\nelse\r\n    window.SmoothScroll = SmoothScroll;\r\n\r\n})();\r\n\r\n\r\n/* Owl Carousel Min Js */\r\n\r\n\"function\"!==typeof Object.create&&(Object.create=function(f){function g(){}g.prototype=f;return new g});\n(function(f,g,k){var l={init:function(a,b){this.$elem=f(b);this.options=f.extend({},f.fn.owlCarousel.options,this.$elem.data(),a);this.userOptions=a;this.loadContent()},loadContent:function(){function a(a){var d,e=\"\";if(\"function\"===typeof b.options.jsonSuccess)b.options.jsonSuccess.apply(this,[a]);else{for(d in a.owl)a.owl.hasOwnProperty(d)&&(e+=a.owl[d].item);b.$elem.html(e)}b.logIn()}var b=this,e;\"function\"===typeof b.options.beforeInit&&b.options.beforeInit.apply(this,[b.$elem]);\"string\"===typeof b.options.jsonPath?\n(e=b.options.jsonPath,f.getJSON(e,a)):b.logIn()},logIn:function(){this.$elem.data(\"owl-originalStyles\",this.$elem.attr(\"style\"));this.$elem.data(\"owl-originalClasses\",this.$elem.attr(\"class\"));this.$elem.css({opacity:0});this.orignalItems=this.options.items;this.checkBrowser();this.wrapperWidth=0;this.checkVisible=null;this.setVars()},setVars:function(){if(0===this.$elem.children().length)return!1;this.baseClass();this.eventTypes();this.$userItems=this.$elem.children();this.itemsAmount=this.$userItems.length;\nthis.wrapItems();this.$owlItems=this.$elem.find(\".owl-item\");this.$owlWrapper=this.$elem.find(\".owl-wrapper\");this.playDirection=\"next\";this.prevItem=0;this.prevArr=[0];this.currentItem=0;this.customEvents();this.onStartup()},onStartup:function(){this.updateItems();this.calculateAll();this.buildControls();this.updateControls();this.response();this.moveEvents();this.stopOnHover();this.owlStatus();!1!==this.options.transitionStyle&&this.transitionTypes(this.options.transitionStyle);!0===this.options.autoPlay&&\n(this.options.autoPlay=5E3);this.play();this.$elem.find(\".owl-wrapper\").css(\"display\",\"block\");this.$elem.is(\":visible\")?this.$elem.css(\"opacity\",1):this.watchVisibility();this.onstartup=!1;this.eachMoveUpdate();\"function\"===typeof this.options.afterInit&&this.options.afterInit.apply(this,[this.$elem])},eachMoveUpdate:function(){!0===this.options.lazyLoad&&this.lazyLoad();!0===this.options.autoHeight&&this.autoHeight();this.onVisibleItems();\"function\"===typeof this.options.afterAction&&this.options.afterAction.apply(this,\n[this.$elem])},updateVars:function(){\"function\"===typeof this.options.beforeUpdate&&this.options.beforeUpdate.apply(this,[this.$elem]);this.watchVisibility();this.updateItems();this.calculateAll();this.updatePosition();this.updateControls();this.eachMoveUpdate();\"function\"===typeof this.options.afterUpdate&&this.options.afterUpdate.apply(this,[this.$elem])},reload:function(){var a=this;g.setTimeout(function(){a.updateVars()},0)},watchVisibility:function(){var a=this;if(!1===a.$elem.is(\":visible\"))a.$elem.css({opacity:0}),\ng.clearInterval(a.autoPlayInterval),g.clearInterval(a.checkVisible);else return!1;a.checkVisible=g.setInterval(function(){a.$elem.is(\":visible\")&&(a.reload(),a.$elem.animate({opacity:1},200),g.clearInterval(a.checkVisible))},500)},wrapItems:function(){this.$userItems.wrapAll('<div class=\"owl-wrapper\">').wrap('<div class=\"owl-item\"></div>');this.$elem.find(\".owl-wrapper\").wrap('<div class=\"owl-wrapper-outer\">');this.wrapperOuter=this.$elem.find(\".owl-wrapper-outer\");this.$elem.css(\"display\",\"block\")},\nbaseClass:function(){var a=this.$elem.hasClass(this.options.baseClass),b=this.$elem.hasClass(this.options.theme);a||this.$elem.addClass(this.options.baseClass);b||this.$elem.addClass(this.options.theme)},updateItems:function(){var a,b;if(!1===this.options.responsive)return!1;if(!0===this.options.singleItem)return this.options.items=this.orignalItems=1,this.options.itemsCustom=!1,this.options.itemsDesktop=!1,this.options.itemsDesktopSmall=!1,this.options.itemsTablet=!1,this.options.itemsTabletSmall=\n!1,this.options.itemsMobile=!1;a=f(this.options.responsiveBaseWidth).width();a>(this.options.itemsDesktop[0]||this.orignalItems)&&(this.options.items=this.orignalItems);if(!1!==this.options.itemsCustom)for(this.options.itemsCustom.sort(function(a,b){return a[0]-b[0]}),b=0;b<this.options.itemsCustom.length;b+=1)this.options.itemsCustom[b][0]<=a&&(this.options.items=this.options.itemsCustom[b][1]);else a<=this.options.itemsDesktop[0]&&!1!==this.options.itemsDesktop&&(this.options.items=this.options.itemsDesktop[1]),\na<=this.options.itemsDesktopSmall[0]&&!1!==this.options.itemsDesktopSmall&&(this.options.items=this.options.itemsDesktopSmall[1]),a<=this.options.itemsTablet[0]&&!1!==this.options.itemsTablet&&(this.options.items=this.options.itemsTablet[1]),a<=this.options.itemsTabletSmall[0]&&!1!==this.options.itemsTabletSmall&&(this.options.items=this.options.itemsTabletSmall[1]),a<=this.options.itemsMobile[0]&&!1!==this.options.itemsMobile&&(this.options.items=this.options.itemsMobile[1]);this.options.items>this.itemsAmount&&\n!0===this.options.itemsScaleUp&&(this.options.items=this.itemsAmount)},response:function(){var a=this,b,e;if(!0!==a.options.responsive)return!1;e=f(g).width();a.resizer=function(){f(g).width()!==e&&(!1!==a.options.autoPlay&&g.clearInterval(a.autoPlayInterval),g.clearTimeout(b),b=g.setTimeout(function(){e=f(g).width();a.updateVars()},a.options.responsiveRefreshRate))};f(g).resize(a.resizer)},updatePosition:function(){this.jumpTo(this.currentItem);!1!==this.options.autoPlay&&this.checkAp()},appendItemsSizes:function(){var a=\nthis,b=0,e=a.itemsAmount-a.options.items;a.$owlItems.each(function(c){var d=f(this);d.css({width:a.itemWidth}).data(\"owl-item\",Number(c));if(0===c%a.options.items||c===e)c>e||(b+=1);d.data(\"owl-roundPages\",b)})},appendWrapperSizes:function(){this.$owlWrapper.css({width:this.$owlItems.length*this.itemWidth*2,left:0});this.appendItemsSizes()},calculateAll:function(){this.calculateWidth();this.appendWrapperSizes();this.loops();this.max()},calculateWidth:function(){this.itemWidth=Math.round(this.$elem.width()/\nthis.options.items)},max:function(){var a=-1*(this.itemsAmount*this.itemWidth-this.options.items*this.itemWidth);this.options.items>this.itemsAmount?this.maximumPixels=a=this.maximumItem=0:(this.maximumItem=this.itemsAmount-this.options.items,this.maximumPixels=a);return a},min:function(){return 0},loops:function(){var a=0,b=0,e,c;this.positionsInArray=[0];this.pagesInArray=[];for(e=0;e<this.itemsAmount;e+=1)b+=this.itemWidth,this.positionsInArray.push(-b),!0===this.options.scrollPerPage&&(c=f(this.$owlItems[e]),\nc=c.data(\"owl-roundPages\"),c!==a&&(this.pagesInArray[a]=this.positionsInArray[e],a=c))},buildControls:function(){if(!0===this.options.navigation||!0===this.options.pagination)this.owlControls=f('<div class=\"owl-controls\"/>').toggleClass(\"clickable\",!this.browser.isTouch).appendTo(this.$elem);!0===this.options.pagination&&this.buildPagination();!0===this.options.navigation&&this.buildButtons()},buildButtons:function(){var a=this,b=f('<div class=\"owl-buttons\"/>');a.owlControls.append(b);a.buttonPrev=\nf(\"<div/>\",{\"class\":\"owl-prev\",html:a.options.navigationText[0]||\"\"});a.buttonNext=f(\"<div/>\",{\"class\":\"owl-next\",html:a.options.navigationText[1]||\"\"});b.append(a.buttonPrev).append(a.buttonNext);b.on(\"touchstart.owlControls mousedown.owlControls\",'div[class^=\"owl\"]',function(a){a.preventDefault()});b.on(\"touchend.owlControls mouseup.owlControls\",'div[class^=\"owl\"]',function(b){b.preventDefault();f(this).hasClass(\"owl-next\")?a.next():a.prev()})},buildPagination:function(){var a=this;a.paginationWrapper=\nf('<div class=\"owl-pagination\"/>');a.owlControls.append(a.paginationWrapper);a.paginationWrapper.on(\"touchend.owlControls mouseup.owlControls\",\".owl-page\",function(b){b.preventDefault();Number(f(this).data(\"owl-page\"))!==a.currentItem&&a.goTo(Number(f(this).data(\"owl-page\")),!0)})},updatePagination:function(){var a,b,e,c,d,g;if(!1===this.options.pagination)return!1;this.paginationWrapper.html(\"\");a=0;b=this.itemsAmount-this.itemsAmount%this.options.items;for(c=0;c<this.itemsAmount;c+=1)0===c%this.options.items&&\n(a+=1,b===c&&(e=this.itemsAmount-this.options.items),d=f(\"<div/>\",{\"class\":\"owl-page\"}),g=f(\"<span></span>\",{text:!0===this.options.paginationNumbers?a:\"\",\"class\":!0===this.options.paginationNumbers?\"owl-numbers\":\"\"}),d.append(g),d.data(\"owl-page\",b===c?e:c),d.data(\"owl-roundPages\",a),this.paginationWrapper.append(d));this.checkPagination()},checkPagination:function(){var a=this;if(!1===a.options.pagination)return!1;a.paginationWrapper.find(\".owl-page\").each(function(){f(this).data(\"owl-roundPages\")===\nf(a.$owlItems[a.currentItem]).data(\"owl-roundPages\")&&(a.paginationWrapper.find(\".owl-page\").removeClass(\"active\"),f(this).addClass(\"active\"))})},checkNavigation:function(){if(!1===this.options.navigation)return!1;!1===this.options.rewindNav&&(0===this.currentItem&&0===this.maximumItem?(this.buttonPrev.addClass(\"disabled\"),this.buttonNext.addClass(\"disabled\")):0===this.currentItem&&0!==this.maximumItem?(this.buttonPrev.addClass(\"disabled\"),this.buttonNext.removeClass(\"disabled\")):this.currentItem===\nthis.maximumItem?(this.buttonPrev.removeClass(\"disabled\"),this.buttonNext.addClass(\"disabled\")):0!==this.currentItem&&this.currentItem!==this.maximumItem&&(this.buttonPrev.removeClass(\"disabled\"),this.buttonNext.removeClass(\"disabled\")))},updateControls:function(){this.updatePagination();this.checkNavigation();this.owlControls&&(this.options.items>=this.itemsAmount?this.owlControls.hide():this.owlControls.show())},destroyControls:function(){this.owlControls&&this.owlControls.remove()},next:function(a){if(this.isTransition)return!1;\nthis.currentItem+=!0===this.options.scrollPerPage?this.options.items:1;if(this.currentItem>this.maximumItem+(!0===this.options.scrollPerPage?this.options.items-1:0))if(!0===this.options.rewindNav)this.currentItem=0,a=\"rewind\";else return this.currentItem=this.maximumItem,!1;this.goTo(this.currentItem,a)},prev:function(a){if(this.isTransition)return!1;this.currentItem=!0===this.options.scrollPerPage&&0<this.currentItem&&this.currentItem<this.options.items?0:this.currentItem-(!0===this.options.scrollPerPage?\nthis.options.items:1);if(0>this.currentItem)if(!0===this.options.rewindNav)this.currentItem=this.maximumItem,a=\"rewind\";else return this.currentItem=0,!1;this.goTo(this.currentItem,a)},goTo:function(a,b,e){var c=this;if(c.isTransition)return!1;\"function\"===typeof c.options.beforeMove&&c.options.beforeMove.apply(this,[c.$elem]);a>=c.maximumItem?a=c.maximumItem:0>=a&&(a=0);c.currentItem=c.owl.currentItem=a;if(!1!==c.options.transitionStyle&&\"drag\"!==e&&1===c.options.items&&!0===c.browser.support3d)return c.swapSpeed(0),\n!0===c.browser.support3d?c.transition3d(c.positionsInArray[a]):c.css2slide(c.positionsInArray[a],1),c.afterGo(),c.singleItemTransition(),!1;a=c.positionsInArray[a];!0===c.browser.support3d?(c.isCss3Finish=!1,!0===b?(c.swapSpeed(\"paginationSpeed\"),g.setTimeout(function(){c.isCss3Finish=!0},c.options.paginationSpeed)):\"rewind\"===b?(c.swapSpeed(c.options.rewindSpeed),g.setTimeout(function(){c.isCss3Finish=!0},c.options.rewindSpeed)):(c.swapSpeed(\"slideSpeed\"),g.setTimeout(function(){c.isCss3Finish=!0},\nc.options.slideSpeed)),c.transition3d(a)):!0===b?c.css2slide(a,c.options.paginationSpeed):\"rewind\"===b?c.css2slide(a,c.options.rewindSpeed):c.css2slide(a,c.options.slideSpeed);c.afterGo()},jumpTo:function(a){\"function\"===typeof this.options.beforeMove&&this.options.beforeMove.apply(this,[this.$elem]);a>=this.maximumItem||-1===a?a=this.maximumItem:0>=a&&(a=0);this.swapSpeed(0);!0===this.browser.support3d?this.transition3d(this.positionsInArray[a]):this.css2slide(this.positionsInArray[a],1);this.currentItem=\nthis.owl.currentItem=a;this.afterGo()},afterGo:function(){this.prevArr.push(this.currentItem);this.prevItem=this.owl.prevItem=this.prevArr[this.prevArr.length-2];this.prevArr.shift(0);this.prevItem!==this.currentItem&&(this.checkPagination(),this.checkNavigation(),this.eachMoveUpdate(),!1!==this.options.autoPlay&&this.checkAp());\"function\"===typeof this.options.afterMove&&this.prevItem!==this.currentItem&&this.options.afterMove.apply(this,[this.$elem])},stop:function(){this.apStatus=\"stop\";g.clearInterval(this.autoPlayInterval)},\ncheckAp:function(){\"stop\"!==this.apStatus&&this.play()},play:function(){var a=this;a.apStatus=\"play\";if(!1===a.options.autoPlay)return!1;g.clearInterval(a.autoPlayInterval);a.autoPlayInterval=g.setInterval(function(){a.next(!0)},a.options.autoPlay)},swapSpeed:function(a){\"slideSpeed\"===a?this.$owlWrapper.css(this.addCssSpeed(this.options.slideSpeed)):\"paginationSpeed\"===a?this.$owlWrapper.css(this.addCssSpeed(this.options.paginationSpeed)):\"string\"!==typeof a&&this.$owlWrapper.css(this.addCssSpeed(a))},\naddCssSpeed:function(a){return{\"-webkit-transition\":\"all \"+a+\"ms ease\",\"-moz-transition\":\"all \"+a+\"ms ease\",\"-o-transition\":\"all \"+a+\"ms ease\",transition:\"all \"+a+\"ms ease\"}},removeTransition:function(){return{\"-webkit-transition\":\"\",\"-moz-transition\":\"\",\"-o-transition\":\"\",transition:\"\"}},doTranslate:function(a){return{\"-webkit-transform\":\"translate3d(\"+a+\"px, 0px, 0px)\",\"-moz-transform\":\"translate3d(\"+a+\"px, 0px, 0px)\",\"-o-transform\":\"translate3d(\"+a+\"px, 0px, 0px)\",\"-ms-transform\":\"translate3d(\"+\na+\"px, 0px, 0px)\",transform:\"translate3d(\"+a+\"px, 0px,0px)\"}},transition3d:function(a){this.$owlWrapper.css(this.doTranslate(a))},css2move:function(a){this.$owlWrapper.css({left:a})},css2slide:function(a,b){var e=this;e.isCssFinish=!1;e.$owlWrapper.stop(!0,!0).animate({left:a},{duration:b||e.options.slideSpeed,complete:function(){e.isCssFinish=!0}})},checkBrowser:function(){var a=k.createElement(\"div\");a.style.cssText=\"  -moz-transform:translate3d(0px, 0px, 0px); -ms-transform:translate3d(0px, 0px, 0px); -o-transform:translate3d(0px, 0px, 0px); -webkit-transform:translate3d(0px, 0px, 0px); transform:translate3d(0px, 0px, 0px)\";\na=a.style.cssText.match(/translate3d\\(0px, 0px, 0px\\)/g);this.browser={support3d:null!==a&&1===a.length,isTouch:\"ontouchstart\"in g||g.navigator.msMaxTouchPoints}},moveEvents:function(){if(!1!==this.options.mouseDrag||!1!==this.options.touchDrag)this.gestures(),this.disabledEvents()},eventTypes:function(){var a=[\"s\",\"e\",\"x\"];this.ev_types={};!0===this.options.mouseDrag&&!0===this.options.touchDrag?a=[\"touchstart.owl mousedown.owl\",\"touchmove.owl mousemove.owl\",\"touchend.owl touchcancel.owl mouseup.owl\"]:\n!1===this.options.mouseDrag&&!0===this.options.touchDrag?a=[\"touchstart.owl\",\"touchmove.owl\",\"touchend.owl touchcancel.owl\"]:!0===this.options.mouseDrag&&!1===this.options.touchDrag&&(a=[\"mousedown.owl\",\"mousemove.owl\",\"mouseup.owl\"]);this.ev_types.start=a[0];this.ev_types.move=a[1];this.ev_types.end=a[2]},disabledEvents:function(){this.$elem.on(\"dragstart.owl\",function(a){a.preventDefault()});this.$elem.on(\"mousedown.disableTextSelect\",function(a){return f(a.target).is(\"input, textarea, select, option\")})},\ngestures:function(){function a(a){if(void 0!==a.touches)return{x:a.touches[0].pageX,y:a.touches[0].pageY};if(void 0===a.touches){if(void 0!==a.pageX)return{x:a.pageX,y:a.pageY};if(void 0===a.pageX)return{x:a.clientX,y:a.clientY}}}function b(a){\"on\"===a?(f(k).on(d.ev_types.move,e),f(k).on(d.ev_types.end,c)):\"off\"===a&&(f(k).off(d.ev_types.move),f(k).off(d.ev_types.end))}function e(b){b=b.originalEvent||b||g.event;d.newPosX=a(b).x-h.offsetX;d.newPosY=a(b).y-h.offsetY;d.newRelativeX=d.newPosX-h.relativePos;\n\"function\"===typeof d.options.startDragging&&!0!==h.dragging&&0!==d.newRelativeX&&(h.dragging=!0,d.options.startDragging.apply(d,[d.$elem]));(8<d.newRelativeX||-8>d.newRelativeX)&&!0===d.browser.isTouch&&(void 0!==b.preventDefault?b.preventDefault():b.returnValue=!1,h.sliding=!0);(10<d.newPosY||-10>d.newPosY)&&!1===h.sliding&&f(k).off(\"touchmove.owl\");d.newPosX=Math.max(Math.min(d.newPosX,d.newRelativeX/5),d.maximumPixels+d.newRelativeX/5);!0===d.browser.support3d?d.transition3d(d.newPosX):d.css2move(d.newPosX)}\nfunction c(a){a=a.originalEvent||a||g.event;var c;a.target=a.target||a.srcElement;h.dragging=!1;!0!==d.browser.isTouch&&d.$owlWrapper.removeClass(\"grabbing\");d.dragDirection=0>d.newRelativeX?d.owl.dragDirection=\"left\":d.owl.dragDirection=\"right\";0!==d.newRelativeX&&(c=d.getNewPosition(),d.goTo(c,!1,\"drag\"),h.targetElement===a.target&&!0!==d.browser.isTouch&&(f(a.target).on(\"click.disable\",function(a){a.stopImmediatePropagation();a.stopPropagation();a.preventDefault();f(a.target).off(\"click.disable\")}),\na=f._data(a.target,\"events\").click,c=a.pop(),a.splice(0,0,c)));b(\"off\")}var d=this,h={offsetX:0,offsetY:0,baseElWidth:0,relativePos:0,position:null,minSwipe:null,maxSwipe:null,sliding:null,dargging:null,targetElement:null};d.isCssFinish=!0;d.$elem.on(d.ev_types.start,\".owl-wrapper\",function(c){c=c.originalEvent||c||g.event;var e;if(3===c.which)return!1;if(!(d.itemsAmount<=d.options.items)){if(!1===d.isCssFinish&&!d.options.dragBeforeAnimFinish||!1===d.isCss3Finish&&!d.options.dragBeforeAnimFinish)return!1;\n!1!==d.options.autoPlay&&g.clearInterval(d.autoPlayInterval);!0===d.browser.isTouch||d.$owlWrapper.hasClass(\"grabbing\")||d.$owlWrapper.addClass(\"grabbing\");d.newPosX=0;d.newRelativeX=0;f(this).css(d.removeTransition());e=f(this).position();h.relativePos=e.left;h.offsetX=a(c).x-e.left;h.offsetY=a(c).y-e.top;b(\"on\");h.sliding=!1;h.targetElement=c.target||c.srcElement}})},getNewPosition:function(){var a=this.closestItem();a>this.maximumItem?a=this.currentItem=this.maximumItem:0<=this.newPosX&&(this.currentItem=\na=0);return a},closestItem:function(){var a=this,b=!0===a.options.scrollPerPage?a.pagesInArray:a.positionsInArray,e=a.newPosX,c=null;f.each(b,function(d,g){e-a.itemWidth/20>b[d+1]&&e-a.itemWidth/20<g&&\"left\"===a.moveDirection()?(c=g,a.currentItem=!0===a.options.scrollPerPage?f.inArray(c,a.positionsInArray):d):e+a.itemWidth/20<g&&e+a.itemWidth/20>(b[d+1]||b[d]-a.itemWidth)&&\"right\"===a.moveDirection()&&(!0===a.options.scrollPerPage?(c=b[d+1]||b[b.length-1],a.currentItem=f.inArray(c,a.positionsInArray)):\n(c=b[d+1],a.currentItem=d+1))});return a.currentItem},moveDirection:function(){var a;0>this.newRelativeX?(a=\"right\",this.playDirection=\"next\"):(a=\"left\",this.playDirection=\"prev\");return a},customEvents:function(){var a=this;a.$elem.on(\"owl.next\",function(){a.next()});a.$elem.on(\"owl.prev\",function(){a.prev()});a.$elem.on(\"owl.play\",function(b,e){a.options.autoPlay=e;a.play();a.hoverStatus=\"play\"});a.$elem.on(\"owl.stop\",function(){a.stop();a.hoverStatus=\"stop\"});a.$elem.on(\"owl.goTo\",function(b,e){a.goTo(e)});\na.$elem.on(\"owl.jumpTo\",function(b,e){a.jumpTo(e)})},stopOnHover:function(){var a=this;!0===a.options.stopOnHover&&!0!==a.browser.isTouch&&!1!==a.options.autoPlay&&(a.$elem.on(\"mouseover\",function(){a.stop()}),a.$elem.on(\"mouseout\",function(){\"stop\"!==a.hoverStatus&&a.play()}))},lazyLoad:function(){var a,b,e,c,d;if(!1===this.options.lazyLoad)return!1;for(a=0;a<this.itemsAmount;a+=1)b=f(this.$owlItems[a]),\"loaded\"!==b.data(\"owl-loaded\")&&(e=b.data(\"owl-item\"),c=b.find(\".lazyOwl\"),\"string\"!==typeof c.data(\"src\")?\nb.data(\"owl-loaded\",\"loaded\"):(void 0===b.data(\"owl-loaded\")&&(c.hide(),b.addClass(\"loading\").data(\"owl-loaded\",\"checked\")),(d=!0===this.options.lazyFollow?e>=this.currentItem:!0)&&e<this.currentItem+this.options.items&&c.length&&this.lazyPreload(b,c)))},lazyPreload:function(a,b){function e(){a.data(\"owl-loaded\",\"loaded\").removeClass(\"loading\");b.removeAttr(\"data-src\");\"fade\"===d.options.lazyEffect?b.fadeIn(400):b.show();\"function\"===typeof d.options.afterLazyLoad&&d.options.afterLazyLoad.apply(this,\n[d.$elem])}function c(){f+=1;d.completeImg(b.get(0))||!0===k?e():100>=f?g.setTimeout(c,100):e()}var d=this,f=0,k;\"DIV\"===b.prop(\"tagName\")?(b.css(\"background-image\",\"url(\"+b.data(\"src\")+\")\"),k=!0):b[0].src=b.data(\"src\");c()},autoHeight:function(){function a(){var a=f(e.$owlItems[e.currentItem]).height();e.wrapperOuter.css(\"height\",a+\"px\");e.wrapperOuter.hasClass(\"autoHeight\")||g.setTimeout(function(){e.wrapperOuter.addClass(\"autoHeight\")},0)}function b(){d+=1;e.completeImg(c.get(0))?a():100>=d?g.setTimeout(b,\n100):e.wrapperOuter.css(\"height\",\"\")}var e=this,c=f(e.$owlItems[e.currentItem]).find(\"img\"),d;void 0!==c.get(0)?(d=0,b()):a()},completeImg:function(a){return!a.complete||\"undefined\"!==typeof a.naturalWidth&&0===a.naturalWidth?!1:!0},onVisibleItems:function(){var a;!0===this.options.addClassActive&&this.$owlItems.removeClass(\"active\");this.visibleItems=[];for(a=this.currentItem;a<this.currentItem+this.options.items;a+=1)this.visibleItems.push(a),!0===this.options.addClassActive&&f(this.$owlItems[a]).addClass(\"active\");\nthis.owl.visibleItems=this.visibleItems},transitionTypes:function(a){this.outClass=\"owl-\"+a+\"-out\";this.inClass=\"owl-\"+a+\"-in\"},singleItemTransition:function(){var a=this,b=a.outClass,e=a.inClass,c=a.$owlItems.eq(a.currentItem),d=a.$owlItems.eq(a.prevItem),f=Math.abs(a.positionsInArray[a.currentItem])+a.positionsInArray[a.prevItem],g=Math.abs(a.positionsInArray[a.currentItem])+a.itemWidth/2;a.isTransition=!0;a.$owlWrapper.addClass(\"owl-origin\").css({\"-webkit-transform-origin\":g+\"px\",\"-moz-perspective-origin\":g+\n\"px\",\"perspective-origin\":g+\"px\"});d.css({position:\"relative\",left:f+\"px\"}).addClass(b).on(\"webkitAnimationEnd oAnimationEnd MSAnimationEnd animationend\",function(){a.endPrev=!0;d.off(\"webkitAnimationEnd oAnimationEnd MSAnimationEnd animationend\");a.clearTransStyle(d,b)});c.addClass(e).on(\"webkitAnimationEnd oAnimationEnd MSAnimationEnd animationend\",function(){a.endCurrent=!0;c.off(\"webkitAnimationEnd oAnimationEnd MSAnimationEnd animationend\");a.clearTransStyle(c,e)})},clearTransStyle:function(a,\nb){a.css({position:\"\",left:\"\"}).removeClass(b);this.endPrev&&this.endCurrent&&(this.$owlWrapper.removeClass(\"owl-origin\"),this.isTransition=this.endCurrent=this.endPrev=!1)},owlStatus:function(){this.owl={userOptions:this.userOptions,baseElement:this.$elem,userItems:this.$userItems,owlItems:this.$owlItems,currentItem:this.currentItem,prevItem:this.prevItem,visibleItems:this.visibleItems,isTouch:this.browser.isTouch,browser:this.browser,dragDirection:this.dragDirection}},clearEvents:function(){this.$elem.off(\".owl owl mousedown.disableTextSelect\");\nf(k).off(\".owl owl\");f(g).off(\"resize\",this.resizer)},unWrap:function(){0!==this.$elem.children().length&&(this.$owlWrapper.unwrap(),this.$userItems.unwrap().unwrap(),this.owlControls&&this.owlControls.remove());this.clearEvents();this.$elem.attr(\"style\",this.$elem.data(\"owl-originalStyles\")||\"\").attr(\"class\",this.$elem.data(\"owl-originalClasses\"))},destroy:function(){this.stop();g.clearInterval(this.checkVisible);this.unWrap();this.$elem.removeData()},reinit:function(a){a=f.extend({},this.userOptions,\na);this.unWrap();this.init(a,this.$elem)},addItem:function(a,b){var e;if(!a)return!1;if(0===this.$elem.children().length)return this.$elem.append(a),this.setVars(),!1;this.unWrap();e=void 0===b||-1===b?-1:b;e>=this.$userItems.length||-1===e?this.$userItems.eq(-1).after(a):this.$userItems.eq(e).before(a);this.setVars()},removeItem:function(a){if(0===this.$elem.children().length)return!1;a=void 0===a||-1===a?-1:a;this.unWrap();this.$userItems.eq(a).remove();this.setVars()}};f.fn.owlCarousel=function(a){return this.each(function(){if(!0===\nf(this).data(\"owl-init\"))return!1;f(this).data(\"owl-init\",!0);var b=Object.create(l);b.init(a,this);f.data(this,\"owlCarousel\",b)})};f.fn.owlCarousel.options={items:5,itemsCustom:!1,itemsDesktop:[1199,4],itemsDesktopSmall:[979,3],itemsTablet:[768,2],itemsTabletSmall:!1,itemsMobile:[479,1],singleItem:!1,itemsScaleUp:!1,slideSpeed:200,paginationSpeed:800,rewindSpeed:1E3,autoPlay:!1,stopOnHover:!1,navigation:!1,navigationText:[\"prev\",\"next\"],rewindNav:!0,scrollPerPage:!1,pagination:!0,paginationNumbers:!1,\nresponsive:!0,responsiveRefreshRate:200,responsiveBaseWidth:g,baseClass:\"owl-carousel\",theme:\"owl-theme\",lazyLoad:!1,lazyFollow:!0,lazyEffect:\"fade\",autoHeight:!1,jsonPath:!1,jsonSuccess:!1,dragBeforeAnimFinish:!0,mouseDrag:!0,touchDrag:!0,addClassActive:!1,transitionStyle:!1,beforeUpdate:!1,afterUpdate:!1,beforeInit:!1,afterInit:!1,beforeMove:!1,afterMove:!1,afterAction:!1,startDragging:!1,afterLazyLoad:!1}})(jQuery,window,document);\r\n\r\n\r\n\r\n\r\n/*! WOW - v1.1.3 - 2016-05-06\n*\r\n Copyright (c) 2016 Matthieu Aussaguel;*/\r\n(function(){var a,b,c,d,e,f=function(a,b){return function(){return a.apply(b,arguments)}},g=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b=function(){function a(){}return a.prototype.extend=function(a,b){var c,d;for(c in b)d=b[c],null==a[c]&&(a[c]=d);return a},a.prototype.isMobile=function(a){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(a)},a.prototype.createEvent=function(a,b,c,d){var e;return null==b&&(b=!1),null==c&&(c=!1),null==d&&(d=null),null!=document.createEvent?(e=document.createEvent(\"CustomEvent\"),e.initCustomEvent(a,b,c,d)):null!=document.createEventObject?(e=document.createEventObject(),e.eventType=a):e.eventName=a,e},a.prototype.emitEvent=function(a,b){return null!=a.dispatchEvent?a.dispatchEvent(b):b in(null!=a)?a[b]():\"on\"+b in(null!=a)?a[\"on\"+b]():void 0},a.prototype.addEvent=function(a,b,c){return null!=a.addEventListener?a.addEventListener(b,c,!1):null!=a.attachEvent?a.attachEvent(\"on\"+b,c):a[b]=c},a.prototype.removeEvent=function(a,b,c){return null!=a.removeEventListener?a.removeEventListener(b,c,!1):null!=a.detachEvent?a.detachEvent(\"on\"+b,c):delete a[b]},a.prototype.innerHeight=function(){return\"innerHeight\"in window?window.innerHeight:document.documentElement.clientHeight},a}(),c=this.WeakMap||this.MozWeakMap||(c=function(){function a(){this.keys=[],this.values=[]}return a.prototype.get=function(a){var b,c,d,e,f;for(f=this.keys,b=d=0,e=f.length;e>d;b=++d)if(c=f[b],c===a)return this.values[b]},a.prototype.set=function(a,b){var c,d,e,f,g;for(g=this.keys,c=e=0,f=g.length;f>e;c=++e)if(d=g[c],d===a)return void(this.values[c]=b);return this.keys.push(a),this.values.push(b)},a}()),a=this.MutationObserver||this.WebkitMutationObserver||this.MozMutationObserver||(a=function(){function a(){\"undefined\"!=typeof console&&null!==console&&console.warn(\"MutationObserver is not supported by your browser.\"),\"undefined\"!=typeof console&&null!==console&&console.warn(\"WOW.js cannot detect dom mutations, please call .sync() after loading new content.\")}return a.notSupported=!0,a.prototype.observe=function(){},a}()),d=this.getComputedStyle||function(a,b){return this.getPropertyValue=function(b){var c;return\"float\"===b&&(b=\"styleFloat\"),e.test(b)&&b.replace(e,function(a,b){return b.toUpperCase()}),(null!=(c=a.currentStyle)?c[b]:void 0)||null},this},e=/(\\-([a-z]){1})/g,this.WOW=function(){function e(a){null==a&&(a={}),this.scrollCallback=f(this.scrollCallback,this),this.scrollHandler=f(this.scrollHandler,this),this.resetAnimation=f(this.resetAnimation,this),this.start=f(this.start,this),this.scrolled=!0,this.config=this.util().extend(a,this.defaults),null!=a.scrollContainer&&(this.config.scrollContainer=document.querySelector(a.scrollContainer)),this.animationNameCache=new c,this.wowEvent=this.util().createEvent(this.config.boxClass)}return e.prototype.defaults={boxClass:\"wow\",animateClass:\"animated\",offset:0,mobile:!0,live:!0,callback:null,scrollContainer:null},e.prototype.init=function(){var a;return this.element=window.document.documentElement,\"interactive\"===(a=document.readyState)||\"complete\"===a?this.start():this.util().addEvent(document,\"DOMContentLoaded\",this.start),this.finished=[]},e.prototype.start=function(){var b,c,d,e;if(this.stopped=!1,this.boxes=function(){var a,c,d,e;for(d=this.element.querySelectorAll(\".\"+this.config.boxClass),e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.all=function(){var a,c,d,e;for(d=this.boxes,e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.boxes.length)if(this.disabled())this.resetStyle();else for(e=this.boxes,c=0,d=e.length;d>c;c++)b=e[c],this.applyStyle(b,!0);return this.disabled()||(this.util().addEvent(this.config.scrollContainer||window,\"scroll\",this.scrollHandler),this.util().addEvent(window,\"resize\",this.scrollHandler),this.interval=setInterval(this.scrollCallback,50)),this.config.live?new a(function(a){return function(b){var c,d,e,f,g;for(g=[],c=0,d=b.length;d>c;c++)f=b[c],g.push(function(){var a,b,c,d;for(c=f.addedNodes||[],d=[],a=0,b=c.length;b>a;a++)e=c[a],d.push(this.doSync(e));return d}.call(a));return g}}(this)).observe(document.body,{childList:!0,subtree:!0}):void 0},e.prototype.stop=function(){return this.stopped=!0,this.util().removeEvent(this.config.scrollContainer||window,\"scroll\",this.scrollHandler),this.util().removeEvent(window,\"resize\",this.scrollHandler),null!=this.interval?clearInterval(this.interval):void 0},e.prototype.sync=function(b){return a.notSupported?this.doSync(this.element):void 0},e.prototype.doSync=function(a){var b,c,d,e,f;if(null==a&&(a=this.element),1===a.nodeType){for(a=a.parentNode||a,e=a.querySelectorAll(\".\"+this.config.boxClass),f=[],c=0,d=e.length;d>c;c++)b=e[c],g.call(this.all,b)<0?(this.boxes.push(b),this.all.push(b),this.stopped||this.disabled()?this.resetStyle():this.applyStyle(b,!0),f.push(this.scrolled=!0)):f.push(void 0);return f}},e.prototype.show=function(a){return this.applyStyle(a),a.className=a.className+\" \"+this.config.animateClass,null!=this.config.callback&&this.config.callback(a),this.util().emitEvent(a,this.wowEvent),this.util().addEvent(a,\"animationend\",this.resetAnimation),this.util().addEvent(a,\"oanimationend\",this.resetAnimation),this.util().addEvent(a,\"webkitAnimationEnd\",this.resetAnimation),this.util().addEvent(a,\"MSAnimationEnd\",this.resetAnimation),a},e.prototype.applyStyle=function(a,b){var c,d,e;return d=a.getAttribute(\"data-wow-duration\"),c=a.getAttribute(\"data-wow-delay\"),e=a.getAttribute(\"data-wow-iteration\"),this.animate(function(f){return function(){return f.customStyle(a,b,d,c,e)}}(this))},e.prototype.animate=function(){return\"requestAnimationFrame\"in window?function(a){return window.requestAnimationFrame(a)}:function(a){return a()}}(),e.prototype.resetStyle=function(){var a,b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(a.style.visibility=\"visible\");return e},e.prototype.resetAnimation=function(a){var b;return a.type.toLowerCase().indexOf(\"animationend\")>=0?(b=a.target||a.srcElement,b.className=b.className.replace(this.config.animateClass,\"\").trim()):void 0},e.prototype.customStyle=function(a,b,c,d,e){return b&&this.cacheAnimationName(a),a.style.visibility=b?\"hidden\":\"visible\",c&&this.vendorSet(a.style,{animationDuration:c}),d&&this.vendorSet(a.style,{animationDelay:d}),e&&this.vendorSet(a.style,{animationIterationCount:e}),this.vendorSet(a.style,{animationName:b?\"none\":this.cachedAnimationName(a)}),a},e.prototype.vendors=[\"moz\",\"webkit\"],e.prototype.vendorSet=function(a,b){var c,d,e,f;d=[];for(c in b)e=b[c],a[\"\"+c]=e,d.push(function(){var b,d,g,h;for(g=this.vendors,h=[],b=0,d=g.length;d>b;b++)f=g[b],h.push(a[\"\"+f+c.charAt(0).toUpperCase()+c.substr(1)]=e);return h}.call(this));return d},e.prototype.vendorCSS=function(a,b){var c,e,f,g,h,i;for(h=d(a),g=h.getPropertyCSSValue(b),f=this.vendors,c=0,e=f.length;e>c;c++)i=f[c],g=g||h.getPropertyCSSValue(\"-\"+i+\"-\"+b);return g},e.prototype.animationName=function(a){var b;try{b=this.vendorCSS(a,\"animation-name\").cssText}catch(c){b=d(a).getPropertyValue(\"animation-name\")}return\"none\"===b?\"\":b},e.prototype.cacheAnimationName=function(a){return this.animationNameCache.set(a,this.animationName(a))},e.prototype.cachedAnimationName=function(a){return this.animationNameCache.get(a)},e.prototype.scrollHandler=function(){return this.scrolled=!0},e.prototype.scrollCallback=function(){var a;return!this.scrolled||(this.scrolled=!1,this.boxes=function(){var b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],a&&(this.isVisible(a)?this.show(a):e.push(a));return e}.call(this),this.boxes.length||this.config.live)?void 0:this.stop()},e.prototype.offsetTop=function(a){for(var b;void 0===a.offsetTop;)a=a.parentNode;for(b=a.offsetTop;a=a.offsetParent;)b+=a.offsetTop;return b},e.prototype.isVisible=function(a){var b,c,d,e,f;return c=a.getAttribute(\"data-wow-offset\")||this.config.offset,f=this.config.scrollContainer&&this.config.scrollContainer.scrollTop||window.pageYOffset,e=f+Math.min(this.element.clientHeight,this.util().innerHeight())-c,d=this.offsetTop(a),b=d+a.clientHeight,e>=d&&b>=f},e.prototype.util=function(){return null!=this._util?this._util:this._util=new b},e.prototype.disabled=function(){return!this.config.mobile&&this.util().isMobile(navigator.userAgent)},e}()}).call(this);\r\n\r\n\r\n\r\n/*! Magnific Popup - v1.1.0 - 2016-02-20\n* http://dimsemenov.com/plugins/magnific-popup/\n* Copyright (c) 2016 Dmitry Semenov; */\n!function(a){\"function\"==typeof define&&define.amd?define([\"jquery\"],a):a(\"object\"==typeof exports?require(\"jquery\"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h=\"Close\",i=\"BeforeClose\",j=\"AfterClose\",k=\"BeforeAppend\",l=\"MarkupParse\",m=\"Open\",n=\"Change\",o=\"mfp\",p=\".\"+o,q=\"mfp-ready\",r=\"mfp-removing\",s=\"mfp-prevent-close\",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var f=document.createElement(\"div\");return f.className=\"mfp-\"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace(\"%title%\",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new t,b.init(),a.magnificPopup.instance=b)},B=function(){var a=document.createElement(\"p\").style,b=[\"ms\",\"O\",\"Moz\",\"Webkit\"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+\"Transition\"in a)return!0;return!1};t.prototype={constructor:t,init:function(){var c=navigator.appVersion;b.isLowIE=b.isIE8=document.all&&!document.addEventListener,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f=\"\",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos=\"auto\"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x(\"bg\").on(\"click\"+p,function(){b.close()}),b.wrap=x(\"wrap\").attr(\"tabindex\",-1).on(\"click\"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x(\"container\",b.wrap)),b.contentContainer=x(\"content\"),b.st.preloader&&(b.preloader=x(\"preloader\",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b[\"init\"+j].call(b)}y(\"BeforeOpen\"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+=\" mfp-close-btn-in\"):b.wrap.append(z())),b.st.alignTop&&(f+=\" mfp-align-top\"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:\"hidden\",overflowY:b.st.overflowY}):b.wrap.css({top:v.scrollTop(),position:\"absolute\"}),(b.st.fixedBgPos===!1||\"auto\"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:\"absolute\"}),b.st.enableEscapeKey&&d.on(\"keyup\"+p,function(a){27===a.keyCode&&b.close()}),v.on(\"resize\"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+=\" mfp-auto-cursor\"),f&&b.wrap.addClass(f);var k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a(\"body, html\").css(\"overflow\",\"hidden\"):n.overflow=\"hidden\");var r=b.st.mainClass;return b.isIE7&&(r+=\" mfp-ie7\"),r&&b._addClassToMFP(r),b.updateItemHTML(),y(\"BuildControls\"),a(\"html\").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on(\"focusin\"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var c=r+\" \"+q+\" \";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+\" \"),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:\"\"};b.isIE7?a(\"body, html\").css(\"overflow\",\"\"):e.overflow=\"\",a(\"html\").css(e)}d.off(\"keyup\"+p+\" focusin\"+p),b.ev.off(p),b.wrap.attr(\"class\",\"mfp-wrap\").removeAttr(\"style\"),b.bgOverlay.attr(\"class\",\"mfp-bg\"),b.container.attr(\"class\",\"mfp-container\"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b.st.autoFocusLast&&b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css(\"height\",d),b.wH=d}else b.wH=a||v.height();b.fixedContentPos||b.wrap.css(\"height\",b.wH),y(\"Resize\")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(y(\"BeforeChange\",[b.currItem?b.currItem.type:\"\",d]),b.currItem=c,!b.currTemplate[d]){var f=b.st[d]?b.st[d].markup:!1;y(\"FirstMarkupParse\",f),f?b.currTemplate[d]=a(f):b.currTemplate[d]=!0}e&&e!==c.type&&b.container.removeClass(\"mfp-\"+e+\"-holder\");var g=b[\"get\"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y(\"AfterChange\")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(\".mfp-close\").length||b.content.append(z()):b.content=a:b.content=\"\",y(k),b.container.addClass(\"mfp-\"+c+\"-holder\"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass(\"mfp-\"+f[g])){d=f[g];break}e.src=e.el.attr(\"data-mfp-src\"),e.src||(e.src=e.el.attr(\"href\"))}return e.type=d||b.st.type||\"inline\",e.index=c,e.parsed=!0,b.items[c]=e,y(\"ElementParse\",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e=\"click.magnificPopup\";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var f=void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||!(2===c.which||c.ctrlKey||c.metaKey||c.altKey||c.shiftKey)){var g=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass(\"mfp-s-\"+c),d||\"loading\"!==a||(d=b.st.tLoading);var e={status:a,text:d};y(\"UpdateStatus\",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find(\"a\").on(\"click\",function(a){a.stopImmediatePropagation()}),b.container.addClass(\"mfp-s-\"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass(\"mfp-close\")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void 0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(c,d){if(void 0===d||d===!1)return!0;if(e=c.split(\"_\"),e.length>1){var f=b.find(p+\"-\"+e[0]);if(f.length>0){var g=e[1];\"replaceWith\"===g?f[0]!==d[0]&&f.replaceWith(d):\"img\"===g?f.is(\"img\")?f.attr(\"src\",d):f.replaceWith(a(\"<img>\").attr(\"src\",d).attr(\"class\",f.attr(\"class\"))):f.attr(e[1],d)}}else b.find(p+\"-\"+c).html(d)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement(\"div\");a.style.cssText=\"width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;\",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:\"\",preloader:!0,focus:\"\",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:\"auto\",fixedBgPos:\"auto\",overflowY:\"auto\",closeMarkup:'<button title=\"%title%\" type=\"button\" class=\"mfp-close\">&#215;</button>',tClose:\"Close (Esc)\",tLoading:\"Loading...\",autoFocusLast:!0}},a.fn.magnificPopup=function(c){A();var d=a(this);if(\"string\"==typeof c)if(\"open\"===c){var e,f=u?d.data(\"magnificPopup\"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),u?d.data(\"magnificPopup\",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F=\"inline\",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:\"hide\",markup:\"\",tNotFound:\"Content not found\"},proto:{initInline:function(){b.types.push(F),w(h+\".\"+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C=\"mfp-\"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus(\"ready\")}else b.updateStatus(\"error\",e.tNotFound),f=a(\"<div>\");return c.inlineElement=f,f}return b.updateStatus(\"ready\"),b._parseMarkup(d,{},c),d}}});var H,I=\"ajax\",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:\"mfp-ajax-cur\",tError:'<a href=\"%url%\">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+\".\"+I,K),w(\"BeforeChange.\"+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus(\"loading\");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y(\"ParseAjax\",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus(\"ready\"),y(\"AjaxContentAdded\")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus(\"error\",b.st.ajax.tError.replace(\"%url%\",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),\"\"}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||\"\"}return\"\"};a.magnificPopup.registerModule(\"image\",{options:{markup:'<div class=\"mfp-figure\"><div class=\"mfp-close\"></div><figure><div class=\"mfp-img\"></div><figcaption><div class=\"mfp-bottom-bar\"><div class=\"mfp-title\"></div><div class=\"mfp-counter\"></div></div></figcaption></figure></div>',cursor:\"mfp-zoom-out-cur\",titleSrc:\"title\",verticalFit:!0,tError:'<a href=\"%url%\">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=\".image\";b.types.push(\"image\"),w(m+d,function(){\"image\"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off(\"resize\"+p)}),w(\"Resize\"+d,b.resizeImage),b.isLowIE&&w(\"AfterChange\",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css(\"padding-top\"),10)+parseInt(a.img.css(\"padding-bottom\"),10)),a.img.css(\"max-height\",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y(\"ImageHasSize\",a),a.imgHidden&&(b.content&&b.content.removeClass(\"mfp-loading\"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(\".mfploader\"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus(\"ready\")),c.hasSize=!0,c.loaded=!0,y(\"ImageLoadComplete\")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(\".mfploader\"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus(\"error\",h.tError.replace(\"%url%\",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(\".mfp-img\");if(i.length){var j=document.createElement(\"img\");j.className=\"mfp-img\",c.el&&c.el.find(\"img\").length&&(j.alt=c.el.find(\"img\").attr(\"alt\")),c.img=a(j).on(\"load.mfploader\",f).on(\"error.mfploader\",g),j.src=c.src,i.is(\"img\")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass(\"mfp-loading\"),b.updateStatus(\"error\",h.tError.replace(\"%url%\",c.src))):(d.removeClass(\"mfp-loading\"),b.updateStatus(\"ready\")),d):(b.updateStatus(\"loading\"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass(\"mfp-loading\"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement(\"p\").style.MozTransform),N};a.magnificPopup.registerModule(\"zoom\",{options:{enabled:!1,easing:\"ease-in-out\",duration:300,opener:function(a){return a.is(\"img\")?a:a.find(\"img\")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=\".zoom\";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr(\"style\").removeAttr(\"class\").addClass(\"mfp-animated-image\"),d=\"all \"+c.duration/1e3+\"s \"+c.easing,e={position:\"fixed\",zIndex:9999,left:0,top:0,\"-webkit-backface-visibility\":\"hidden\"},f=\"transition\";return e[\"-webkit-\"+f]=e[\"-moz-\"+f]=e[\"-o-\"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css(\"visibility\",\"visible\")};w(\"BuildControls\"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css(\"visibility\",\"hidden\"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y(\"ZoomAnimationEnded\")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css(\"visibility\",\"hidden\"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return\"image\"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css(\"padding-top\"),10),g=parseInt(d.css(\"padding-bottom\"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h[\"-moz-transform\"]=h.transform=\"translate(\"+e.left+\"px,\"+e.top+\"px)\":(h.left=e.left,h.top=e.top),h}}});var P=\"iframe\",Q=\"//about:blank\",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find(\"iframe\");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css(\"display\",a?\"block\":\"none\"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div class=\"mfp-iframe-scaler\"><div class=\"mfp-close\"></div><iframe class=\"mfp-iframe\" src=\"//about:blank\" frameborder=\"0\" allowfullscreen></iframe></div>',srcAction:\"iframe_src\",patterns:{youtube:{index:\"youtube.com\",id:\"v=\",src:\"//www.youtube.com/embed/%id%?autoplay=1\"},vimeo:{index:\"vimeo.com/\",id:\"/\",src:\"//player.vimeo.com/video/%id%?autoplay=1\"},gmaps:{index:\"//maps.google.\",src:\"%id%&output=embed\"}}},proto:{initIframe:function(){b.types.push(P),w(\"BeforeChange\",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+\".\"+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e=\"string\"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace(\"%id%\",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus(\"ready\"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule(\"gallery\",{options:{enabled:!1,arrowMarkup:'<button title=\"%title%\" type=\"button\" class=\"mfp-arrow mfp-arrow-%dir%\"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:\"Previous (Left arrow key)\",tNext:\"Next (Right arrow key)\",tCounter:\"%curr% of %total%\"},proto:{initGallery:function(){var c=b.st.gallery,e=\".mfp-gallery\";return b.direction=!0,c&&c.enabled?(f+=\" mfp-gallery\",w(m+e,function(){c.navigateByImgClick&&b.wrap.on(\"click\"+e,\".mfp-img\",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on(\"keydown\"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w(\"UpdateStatus\"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):\"\"}),w(\"BuildControls\"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,\"left\")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,\"right\")).addClass(s);e.click(function(){b.prev()}),f.click(function(){b.next()}),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off(\"click\"+e),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y(\"LazyLoad\",d),\"image\"===d.type&&(d.img=a('<img class=\"mfp-img\" />').on(\"load.mfploader\",function(){d.hasSize=!0}).on(\"error.mfploader\",function(){d.hasSize=!0,d.loadError=!0,y(\"LazyLoadError\",d)}).attr(\"src\",d.src)),d.preloaded=!0}}}});var U=\"retina\";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\\.\\w+$/,function(a){return\"@2x\"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w(\"ImageHasSize.\"+U,function(a,b){b.img.css({\"max-width\":b.img[0].naturalWidth/c,width:\"100%\"})}),w(\"ElementParse.\"+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),A()});\r\n\r\n\r\n\r\n\r\n// Generated by CoffeeScript 1.6.2\r\n/*\r\njQuery Waypoints - v2.0.3\r\nCopyright (c) 2011-2013 Caleb Troughton\r\nDual licensed under the MIT license and GPL license.\r\nhttps://github.com/imakewebthings/jquery-waypoints/blob/master/licenses.txt\r\n*/\r\n(function(){var t=[].indexOf||function(t){for(var e=0,n=this.length;e<n;e++){if(e in this&&this[e]===t)return e}return-1},e=[].slice;(function(t,e){if(typeof define===\"function\"&&define.amd){return define(\"waypoints\",[\"jquery\"],function(n){return e(n,t)})}else{return e(t.jQuery,t)}})(this,function(n,r){var i,o,l,s,f,u,a,c,h,d,p,y,v,w,g,m;i=n(r);c=t.call(r,\"ontouchstart\")>=0;s={horizontal:{},vertical:{}};f=1;a={};u=\"waypoints-context-id\";p=\"resize.waypoints\";y=\"scroll.waypoints\";v=1;w=\"waypoints-waypoint-ids\";g=\"waypoint\";m=\"waypoints\";o=function(){function t(t){var e=this;this.$element=t;this.element=t[0];this.didResize=false;this.didScroll=false;this.id=\"context\"+f++;this.oldScroll={x:t.scrollLeft(),y:t.scrollTop()};this.waypoints={horizontal:{},vertical:{}};t.data(u,this.id);a[this.id]=this;t.bind(y,function(){var t;if(!(e.didScroll||c)){e.didScroll=true;t=function(){e.doScroll();return e.didScroll=false};return r.setTimeout(t,n[m].settings.scrollThrottle)}});t.bind(p,function(){var t;if(!e.didResize){e.didResize=true;t=function(){n[m](\"refresh\");return e.didResize=false};return r.setTimeout(t,n[m].settings.resizeThrottle)}})}t.prototype.doScroll=function(){var t,e=this;t={horizontal:{newScroll:this.$element.scrollLeft(),oldScroll:this.oldScroll.x,forward:\"right\",backward:\"left\"},vertical:{newScroll:this.$element.scrollTop(),oldScroll:this.oldScroll.y,forward:\"down\",backward:\"up\"}};if(c&&(!t.vertical.oldScroll||!t.vertical.newScroll)){n[m](\"refresh\")}n.each(t,function(t,r){var i,o,l;l=[];o=r.newScroll>r.oldScroll;i=o?r.forward:r.backward;n.each(e.waypoints[t],function(t,e){var n,i;if(r.oldScroll<(n=e.offset)&&n<=r.newScroll){return l.push(e)}else if(r.newScroll<(i=e.offset)&&i<=r.oldScroll){return l.push(e)}});l.sort(function(t,e){return t.offset-e.offset});if(!o){l.reverse()}return n.each(l,function(t,e){if(e.options.continuous||t===l.length-1){return e.trigger([i])}})});return this.oldScroll={x:t.horizontal.newScroll,y:t.vertical.newScroll}};t.prototype.refresh=function(){var t,e,r,i=this;r=n.isWindow(this.element);e=this.$element.offset();this.doScroll();t={horizontal:{contextOffset:r?0:e.left,contextScroll:r?0:this.oldScroll.x,contextDimension:this.$element.width(),oldScroll:this.oldScroll.x,forward:\"right\",backward:\"left\",offsetProp:\"left\"},vertical:{contextOffset:r?0:e.top,contextScroll:r?0:this.oldScroll.y,contextDimension:r?n[m](\"viewportHeight\"):this.$element.height(),oldScroll:this.oldScroll.y,forward:\"down\",backward:\"up\",offsetProp:\"top\"}};return n.each(t,function(t,e){return n.each(i.waypoints[t],function(t,r){var i,o,l,s,f;i=r.options.offset;l=r.offset;o=n.isWindow(r.element)?0:r.$element.offset()[e.offsetProp];if(n.isFunction(i)){i=i.apply(r.element)}else if(typeof i===\"string\"){i=parseFloat(i);if(r.options.offset.indexOf(\"%\")>-1){i=Math.ceil(e.contextDimension*i/100)}}r.offset=o-e.contextOffset+e.contextScroll-i;if(r.options.onlyOnScroll&&l!=null||!r.enabled){return}if(l!==null&&l<(s=e.oldScroll)&&s<=r.offset){return r.trigger([e.backward])}else if(l!==null&&l>(f=e.oldScroll)&&f>=r.offset){return r.trigger([e.forward])}else if(l===null&&e.oldScroll>=r.offset){return r.trigger([e.forward])}})})};t.prototype.checkEmpty=function(){if(n.isEmptyObject(this.waypoints.horizontal)&&n.isEmptyObject(this.waypoints.vertical)){this.$element.unbind([p,y].join(\" \"));return delete a[this.id]}};return t}();l=function(){function t(t,e,r){var i,o;r=n.extend({},n.fn[g].defaults,r);if(r.offset===\"bottom-in-view\"){r.offset=function(){var t;t=n[m](\"viewportHeight\");if(!n.isWindow(e.element)){t=e.$element.height()}return t-n(this).outerHeight()}}this.$element=t;this.element=t[0];this.axis=r.horizontal?\"horizontal\":\"vertical\";this.callback=r.handler;this.context=e;this.enabled=r.enabled;this.id=\"waypoints\"+v++;this.offset=null;this.options=r;e.waypoints[this.axis][this.id]=this;s[this.axis][this.id]=this;i=(o=t.data(w))!=null?o:[];i.push(this.id);t.data(w,i)}t.prototype.trigger=function(t){if(!this.enabled){return}if(this.callback!=null){this.callback.apply(this.element,t)}if(this.options.triggerOnce){return this.destroy()}};t.prototype.disable=function(){return this.enabled=false};t.prototype.enable=function(){this.context.refresh();return this.enabled=true};t.prototype.destroy=function(){delete s[this.axis][this.id];delete this.context.waypoints[this.axis][this.id];return this.context.checkEmpty()};t.getWaypointsByElement=function(t){var e,r;r=n(t).data(w);if(!r){return[]}e=n.extend({},s.horizontal,s.vertical);return n.map(r,function(t){return e[t]})};return t}();d={init:function(t,e){var r;if(e==null){e={}}if((r=e.handler)==null){e.handler=t}this.each(function(){var t,r,i,s;t=n(this);i=(s=e.context)!=null?s:n.fn[g].defaults.context;if(!n.isWindow(i)){i=t.closest(i)}i=n(i);r=a[i.data(u)];if(!r){r=new o(i)}return new l(t,r,e)});n[m](\"refresh\");return this},disable:function(){return d._invoke(this,\"disable\")},enable:function(){return d._invoke(this,\"enable\")},destroy:function(){return d._invoke(this,\"destroy\")},prev:function(t,e){return d._traverse.call(this,t,e,function(t,e,n){if(e>0){return t.push(n[e-1])}})},next:function(t,e){return d._traverse.call(this,t,e,function(t,e,n){if(e<n.length-1){return t.push(n[e+1])}})},_traverse:function(t,e,i){var o,l;if(t==null){t=\"vertical\"}if(e==null){e=r}l=h.aggregate(e);o=[];this.each(function(){var e;e=n.inArray(this,l[t]);return i(o,e,l[t])});return this.pushStack(o)},_invoke:function(t,e){t.each(function(){var t;t=l.getWaypointsByElement(this);return n.each(t,function(t,n){n[e]();return true})});return this}};n.fn[g]=function(){var t,r;r=arguments[0],t=2<=arguments.length?e.call(arguments,1):[];if(d[r]){return d[r].apply(this,t)}else if(n.isFunction(r)){return d.init.apply(this,arguments)}else if(n.isPlainObject(r)){return d.init.apply(this,[null,r])}else if(!r){return n.error(\"jQuery Waypoints needs a callback function or handler option.\")}else{return n.error(\"The \"+r+\" method does not exist in jQuery Waypoints.\")}};n.fn[g].defaults={context:r,continuous:true,enabled:true,horizontal:false,offset:0,triggerOnce:false};h={refresh:function(){return n.each(a,function(t,e){return e.refresh()})},viewportHeight:function(){var t;return(t=r.innerHeight)!=null?t:i.height()},aggregate:function(t){var e,r,i;e=s;if(t){e=(i=a[n(t).data(u)])!=null?i.waypoints:void 0}if(!e){return[]}r={horizontal:[],vertical:[]};n.each(r,function(t,i){n.each(e[t],function(t,e){return i.push(e)});i.sort(function(t,e){return t.offset-e.offset});r[t]=n.map(i,function(t){return t.element});return r[t]=n.unique(r[t])});return r},above:function(t){if(t==null){t=r}return h._filter(t,\"vertical\",function(t,e){return e.offset<=t.oldScroll.y})},below:function(t){if(t==null){t=r}return h._filter(t,\"vertical\",function(t,e){return e.offset>t.oldScroll.y})},left:function(t){if(t==null){t=r}return h._filter(t,\"horizontal\",function(t,e){return e.offset<=t.oldScroll.x})},right:function(t){if(t==null){t=r}return h._filter(t,\"horizontal\",function(t,e){return e.offset>t.oldScroll.x})},enable:function(){return h._invoke(\"enable\")},disable:function(){return h._invoke(\"disable\")},destroy:function(){return h._invoke(\"destroy\")},extendFn:function(t,e){return d[t]=e},_invoke:function(t){var e;e=n.extend({},s.vertical,s.horizontal);return n.each(e,function(e,n){n[t]();return true})},_filter:function(t,e,r){var i,o;i=a[n(t).data(u)];if(!i){return[]}o=[];n.each(i.waypoints[e],function(t,e){if(r(i,e)){return o.push(e)}});o.sort(function(t,e){return t.offset-e.offset});return n.map(o,function(t){return t.element})}};n[m]=function(){var t,n;n=arguments[0],t=2<=arguments.length?e.call(arguments,1):[];if(h[n]){return h[n].apply(null,t)}else{return h.aggregate.call(null,n)}};n[m].settings={resizeThrottle:100,scrollThrottle:30};return i.load(function(){return n[m](\"refresh\")})})}).call(this);\r\n\r\n\r\n\r\n/*!\r\n * imagesLoaded PACKAGED v4.1.1\r\n * JavaScript is all like \"You images are done yet or what?\"\r\n * MIT License\r\n */\r\n\r\n!function(t,e){\"function\"==typeof define&&define.amd?define(\"ev-emitter/ev-emitter\",e):\"object\"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(\"undefined\"!=typeof window?window:this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{};return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){\"use strict\";\"function\"==typeof define&&define.amd?define([\"ev-emitter/ev-emitter\"],function(i){return e(t,i)}):\"object\"==typeof module&&module.exports?module.exports=e(t,require(\"ev-emitter\")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i];return t}function n(t){var e=[];if(Array.isArray(t))e=t;else if(\"number\"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i]);else e.push(t);return e}function o(t,e,r){return this instanceof o?(\"string\"==typeof t&&(t=document.querySelectorAll(t)),this.elements=n(t),this.options=i({},this.options),\"function\"==typeof e?r=e:i(this.options,e),r&&this.on(\"always\",r),this.getImages(),h&&(this.jqDeferred=new h.Deferred),void setTimeout(function(){this.check()}.bind(this))):new o(t,e,r)}function r(t){this.img=t}function s(t,e){this.url=t,this.element=e,this.img=new Image}var h=t.jQuery,a=t.console;o.prototype=Object.create(e.prototype),o.prototype.options={},o.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},o.prototype.addElementImages=function(t){\"IMG\"==t.nodeName&&this.addImage(t),this.options.background===!0&&this.addElementBackgroundImages(t);var e=t.nodeType;if(e&&d[e]){for(var i=t.querySelectorAll(\"img\"),n=0;n<i.length;n++){var o=i[n];this.addImage(o)}if(\"string\"==typeof this.options.background){var r=t.querySelectorAll(this.options.background);for(n=0;n<r.length;n++){var s=r[n];this.addElementBackgroundImages(s)}}}};var d={1:!0,9:!0,11:!0};return o.prototype.addElementBackgroundImages=function(t){var e=getComputedStyle(t);if(e)for(var i=/url\\((['\"])?(.*?)\\1\\)/gi,n=i.exec(e.backgroundImage);null!==n;){var o=n&&n[2];o&&this.addBackground(o,t),n=i.exec(e.backgroundImage)}},o.prototype.addImage=function(t){var e=new r(t);this.images.push(e)},o.prototype.addBackground=function(t,e){var i=new s(t,e);this.images.push(i)},o.prototype.check=function(){function t(t,i,n){setTimeout(function(){e.progress(t,i,n)})}var e=this;return this.progressedCount=0,this.hasAnyBroken=!1,this.images.length?void this.images.forEach(function(e){e.once(\"progress\",t),e.check()}):void this.complete()},o.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent(\"progress\",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount==this.images.length&&this.complete(),this.options.debug&&a&&a.log(\"progress: \"+i,t,e)},o.prototype.complete=function(){var t=this.hasAnyBroken?\"fail\":\"done\";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent(\"always\",[this]),this.jqDeferred){var e=this.hasAnyBroken?\"reject\":\"resolve\";this.jqDeferred[e](this)}},r.prototype=Object.create(e.prototype),r.prototype.check=function(){var t=this.getIsImageComplete();return t?void this.confirm(0!==this.img.naturalWidth,\"naturalWidth\"):(this.proxyImage=new Image,this.proxyImage.addEventListener(\"load\",this),this.proxyImage.addEventListener(\"error\",this),this.img.addEventListener(\"load\",this),this.img.addEventListener(\"error\",this),void(this.proxyImage.src=this.img.src))},r.prototype.getIsImageComplete=function(){return this.img.complete&&void 0!==this.img.naturalWidth},r.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent(\"progress\",[this,this.img,e])},r.prototype.handleEvent=function(t){var e=\"on\"+t.type;this[e]&&this[e](t)},r.prototype.onload=function(){this.confirm(!0,\"onload\"),this.unbindEvents()},r.prototype.onerror=function(){this.confirm(!1,\"onerror\"),this.unbindEvents()},r.prototype.unbindEvents=function(){this.proxyImage.removeEventListener(\"load\",this),this.proxyImage.removeEventListener(\"error\",this),this.img.removeEventListener(\"load\",this),this.img.removeEventListener(\"error\",this)},s.prototype=Object.create(r.prototype),s.prototype.check=function(){this.img.addEventListener(\"load\",this),this.img.addEventListener(\"error\",this),this.img.src=this.url;var t=this.getIsImageComplete();t&&(this.confirm(0!==this.img.naturalWidth,\"naturalWidth\"),this.unbindEvents())},s.prototype.unbindEvents=function(){this.img.removeEventListener(\"load\",this),this.img.removeEventListener(\"error\",this)},s.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent(\"progress\",[this,this.element,e])},o.makeJQueryPlugin=function(e){e=e||t.jQuery,e&&(h=e,h.fn.imagesLoaded=function(t,e){var i=new o(this,t,e);return i.jqDeferred.promise(h(this))})},o.makeJQueryPlugin(),o});\r\n\r\n\r\n/*!\r\n * Isotope PACKAGED v2.2.2\r\n *\r\n * Licensed GPLv3 for open source use\r\n * or Isotope Commercial License for commercial use\r\n *\r\n * http://isotope.metafizzy.co\r\n * Copyright 2015 Metafizzy\r\n */\r\n\r\n!function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if(\"string\"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&\"_\"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l)return l}else f(\"no such method '\"+e+\"' for \"+b+\" instance\");else f(\"cannot call methods on \"+b+\" prior to initialization; attempted to call '\"+e+\"'\")}return this}return this.each(function(){var d=a.data(this,b);d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d))})}}if(a){var f=\"undefined\"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;\"function\"==typeof define&&define.amd?define(\"jquery-bridget/jquery.bridget\",[\"jquery\"],c):c(\"object\"==typeof exports?require(\"jquery\"):a.jQuery)}(window),function(a){function b(b){var c=a.event;return c.target=c.target||c.srcElement||b,c}var c=document.documentElement,d=function(){};c.addEventListener?d=function(a,b,c){a.addEventListener(b,c,!1)}:c.attachEvent&&(d=function(a,c,d){a[c+d]=d.handleEvent?function(){var c=b(a);d.handleEvent.call(d,c)}:function(){var c=b(a);d.call(a,c)},a.attachEvent(\"on\"+c,a[c+d])});var e=function(){};c.removeEventListener?e=function(a,b,c){a.removeEventListener(b,c,!1)}:c.detachEvent&&(e=function(a,b,c){a.detachEvent(\"on\"+b,a[b+c]);try{delete a[b+c]}catch(d){a[b+c]=void 0}});var f={bind:d,unbind:e};\"function\"==typeof define&&define.amd?define(\"eventie/eventie\",f):\"object\"==typeof exports?module.exports=f:a.eventie=f}(window),function(){\"use strict\";function a(){}function b(a,b){for(var c=a.length;c--;)if(a[c].listener===b)return c;return-1}function c(a){return function(){return this[a].apply(this,arguments)}}var d=a.prototype,e=this,f=e.EventEmitter;d.getListeners=function(a){var b,c,d=this._getEvents();if(a instanceof RegExp){b={};for(c in d)d.hasOwnProperty(c)&&a.test(c)&&(b[c]=d[c])}else b=d[a]||(d[a]=[]);return b},d.flattenListeners=function(a){var b,c=[];for(b=0;b<a.length;b+=1)c.push(a[b].listener);return c},d.getListenersAsObject=function(a){var b,c=this.getListeners(a);return c instanceof Array&&(b={},b[a]=c),b||c},d.addListener=function(a,c){var d,e=this.getListenersAsObject(a),f=\"object\"==typeof c;for(d in e)e.hasOwnProperty(d)&&-1===b(e[d],c)&&e[d].push(f?c:{listener:c,once:!1});return this},d.on=c(\"addListener\"),d.addOnceListener=function(a,b){return this.addListener(a,{listener:b,once:!0})},d.once=c(\"addOnceListener\"),d.defineEvent=function(a){return this.getListeners(a),this},d.defineEvents=function(a){for(var b=0;b<a.length;b+=1)this.defineEvent(a[b]);return this},d.removeListener=function(a,c){var d,e,f=this.getListenersAsObject(a);for(e in f)f.hasOwnProperty(e)&&(d=b(f[e],c),-1!==d&&f[e].splice(d,1));return this},d.off=c(\"removeListener\"),d.addListeners=function(a,b){return this.manipulateListeners(!1,a,b)},d.removeListeners=function(a,b){return this.manipulateListeners(!0,a,b)},d.manipulateListeners=function(a,b,c){var d,e,f=a?this.removeListener:this.addListener,g=a?this.removeListeners:this.addListeners;if(\"object\"!=typeof b||b instanceof RegExp)for(d=c.length;d--;)f.call(this,b,c[d]);else for(d in b)b.hasOwnProperty(d)&&(e=b[d])&&(\"function\"==typeof e?f.call(this,d,e):g.call(this,d,e));return this},d.removeEvent=function(a){var b,c=typeof a,d=this._getEvents();if(\"string\"===c)delete d[a];else if(a instanceof RegExp)for(b in d)d.hasOwnProperty(b)&&a.test(b)&&delete d[b];else delete this._events;return this},d.removeAllListeners=c(\"removeEvent\"),d.emitEvent=function(a,b){var c,d,e,f,g=this.getListenersAsObject(a);for(e in g)if(g.hasOwnProperty(e))for(d=g[e].length;d--;)c=g[e][d],c.once===!0&&this.removeListener(a,c.listener),f=c.listener.apply(this,b||[]),f===this._getOnceReturnValue()&&this.removeListener(a,c.listener);return this},d.trigger=c(\"emitEvent\"),d.emit=function(a){var b=Array.prototype.slice.call(arguments,1);return this.emitEvent(a,b)},d.setOnceReturnValue=function(a){return this._onceReturnValue=a,this},d._getOnceReturnValue=function(){return this.hasOwnProperty(\"_onceReturnValue\")?this._onceReturnValue:!0},d._getEvents=function(){return this._events||(this._events={})},a.noConflict=function(){return e.EventEmitter=f,a},\"function\"==typeof define&&define.amd?define(\"eventEmitter/EventEmitter\",[],function(){return a}):\"object\"==typeof module&&module.exports?module.exports=a:e.EventEmitter=a}.call(this),function(a){function b(a){if(a){if(\"string\"==typeof d[a])return a;a=a.charAt(0).toUpperCase()+a.slice(1);for(var b,e=0,f=c.length;f>e;e++)if(b=c[e]+a,\"string\"==typeof d[b])return b}}var c=\"Webkit Moz ms Ms O\".split(\" \"),d=document.documentElement.style;\"function\"==typeof define&&define.amd?define(\"get-style-property/get-style-property\",[],function(){return b}):\"object\"==typeof exports?module.exports=b:a.getStyleProperty=b}(window),function(a,b){function c(a){var b=parseFloat(a),c=-1===a.indexOf(\"%\")&&!isNaN(b);return c&&b}function d(){}function e(){for(var a={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},b=0,c=h.length;c>b;b++){var d=h[b];a[d]=0}return a}function f(b){function d(){if(!m){m=!0;var d=a.getComputedStyle;if(j=function(){var a=d?function(a){return d(a,null)}:function(a){return a.currentStyle};return function(b){var c=a(b);return c||g(\"Style returned \"+c+\". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1\"),c}}(),k=b(\"boxSizing\")){var e=document.createElement(\"div\");e.style.width=\"200px\",e.style.padding=\"1px 2px 3px 4px\",e.style.borderStyle=\"solid\",e.style.borderWidth=\"1px 2px 3px 4px\",e.style[k]=\"border-box\";var f=document.body||document.documentElement;f.appendChild(e);var h=j(e);l=200===c(h.width),f.removeChild(e)}}}function f(a){if(d(),\"string\"==typeof a&&(a=document.querySelector(a)),a&&\"object\"==typeof a&&a.nodeType){var b=j(a);if(\"none\"===b.display)return e();var f={};f.width=a.offsetWidth,f.height=a.offsetHeight;for(var g=f.isBorderBox=!(!k||!b[k]||\"border-box\"!==b[k]),m=0,n=h.length;n>m;m++){var o=h[m],p=b[o];p=i(a,p);var q=parseFloat(p);f[o]=isNaN(q)?0:q}var r=f.paddingLeft+f.paddingRight,s=f.paddingTop+f.paddingBottom,t=f.marginLeft+f.marginRight,u=f.marginTop+f.marginBottom,v=f.borderLeftWidth+f.borderRightWidth,w=f.borderTopWidth+f.borderBottomWidth,x=g&&l,y=c(b.width);y!==!1&&(f.width=y+(x?0:r+v));var z=c(b.height);return z!==!1&&(f.height=z+(x?0:s+w)),f.innerWidth=f.width-(r+v),f.innerHeight=f.height-(s+w),f.outerWidth=f.width+t,f.outerHeight=f.height+u,f}}function i(b,c){if(a.getComputedStyle||-1===c.indexOf(\"%\"))return c;var d=b.style,e=d.left,f=b.runtimeStyle,g=f&&f.left;return g&&(f.left=b.currentStyle.left),d.left=c,c=d.pixelLeft,d.left=e,g&&(f.left=g),c}var j,k,l,m=!1;return f}var g=\"undefined\"==typeof console?d:function(a){console.error(a)},h=[\"paddingLeft\",\"paddingRight\",\"paddingTop\",\"paddingBottom\",\"marginLeft\",\"marginRight\",\"marginTop\",\"marginBottom\",\"borderLeftWidth\",\"borderRightWidth\",\"borderTopWidth\",\"borderBottomWidth\"];\"function\"==typeof define&&define.amd?define(\"get-size/get-size\",[\"get-style-property/get-style-property\"],f):\"object\"==typeof exports?module.exports=f(require(\"desandro-get-style-property\")):a.getSize=f(a.getStyleProperty)}(window),function(a){function b(a){\"function\"==typeof a&&(b.isReady?a():g.push(a))}function c(a){var c=\"readystatechange\"===a.type&&\"complete\"!==f.readyState;b.isReady||c||d()}function d(){b.isReady=!0;for(var a=0,c=g.length;c>a;a++){var d=g[a];d()}}function e(e){return\"complete\"===f.readyState?d():(e.bind(f,\"DOMContentLoaded\",c),e.bind(f,\"readystatechange\",c),e.bind(a,\"load\",c)),b}var f=a.document,g=[];b.isReady=!1,\"function\"==typeof define&&define.amd?define(\"doc-ready/doc-ready\",[\"eventie/eventie\"],e):\"object\"==typeof exports?module.exports=e(require(\"eventie\")):a.docReady=e(a.eventie)}(window),function(a){\"use strict\";function b(a,b){return a[g](b)}function c(a){if(!a.parentNode){var b=document.createDocumentFragment();b.appendChild(a)}}function d(a,b){c(a);for(var d=a.parentNode.querySelectorAll(b),e=0,f=d.length;f>e;e++)if(d[e]===a)return!0;return!1}function e(a,d){return c(a),b(a,d)}var f,g=function(){if(a.matches)return\"matches\";if(a.matchesSelector)return\"matchesSelector\";for(var b=[\"webkit\",\"moz\",\"ms\",\"o\"],c=0,d=b.length;d>c;c++){var e=b[c],f=e+\"MatchesSelector\";if(a[f])return f}}();if(g){var h=document.createElement(\"div\"),i=b(h,\"div\");f=i?b:e}else f=d;\"function\"==typeof define&&define.amd?define(\"matches-selector/matches-selector\",[],function(){return f}):\"object\"==typeof exports?module.exports=f:window.matchesSelector=f}(Element.prototype),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"fizzy-ui-utils/utils\",[\"doc-ready/doc-ready\",\"matches-selector/matches-selector\"],function(c,d){return b(a,c,d)}):\"object\"==typeof exports?module.exports=b(a,require(\"doc-ready\"),require(\"desandro-matches-selector\")):a.fizzyUIUtils=b(a,a.docReady,a.matchesSelector)}(window,function(a,b,c){var d={};d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.modulo=function(a,b){return(a%b+b)%b};var e=Object.prototype.toString;d.isArray=function(a){return\"[object Array]\"==e.call(a)},d.makeArray=function(a){var b=[];if(d.isArray(a))b=a;else if(a&&\"number\"==typeof a.length)for(var c=0,e=a.length;e>c;c++)b.push(a[c]);else b.push(a);return b},d.indexOf=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},d.removeFrom=function(a,b){var c=d.indexOf(a,b);-1!=c&&a.splice(c,1)},d.isElement=\"function\"==typeof HTMLElement||\"object\"==typeof HTMLElement?function(a){return a instanceof HTMLElement}:function(a){return a&&\"object\"==typeof a&&1==a.nodeType&&\"string\"==typeof a.nodeName},d.setText=function(){function a(a,c){b=b||(void 0!==document.documentElement.textContent?\"textContent\":\"innerText\"),a[b]=c}var b;return a}(),d.getParent=function(a,b){for(;a!=document.body;)if(a=a.parentNode,c(a,b))return a},d.getQueryElement=function(a){return\"string\"==typeof a?document.querySelector(a):a},d.handleEvent=function(a){var b=\"on\"+a.type;this[b]&&this[b](a)},d.filterFindElements=function(a,b){a=d.makeArray(a);for(var e=[],f=0,g=a.length;g>f;f++){var h=a[f];if(d.isElement(h))if(b){c(h,b)&&e.push(h);for(var i=h.querySelectorAll(b),j=0,k=i.length;k>j;j++)e.push(i[j])}else e.push(h)}return e},d.debounceMethod=function(a,b,c){var d=a.prototype[b],e=b+\"Timeout\";a.prototype[b]=function(){var a=this[e];a&&clearTimeout(a);var b=arguments,f=this;this[e]=setTimeout(function(){d.apply(f,b),delete f[e]},c||100)}},d.toDashed=function(a){return a.replace(/(.)([A-Z])/g,function(a,b,c){return b+\"-\"+c}).toLowerCase()};var f=a.console;return d.htmlInit=function(c,e){b(function(){for(var b=d.toDashed(e),g=document.querySelectorAll(\".js-\"+b),h=\"data-\"+b+\"-options\",i=0,j=g.length;j>i;i++){var k,l=g[i],m=l.getAttribute(h);try{k=m&&JSON.parse(m)}catch(n){f&&f.error(\"Error parsing \"+h+\" on \"+l.nodeName.toLowerCase()+(l.id?\"#\"+l.id:\"\")+\": \"+n);continue}var o=new c(l,k),p=a.jQuery;p&&p.data(l,e,o)}})},d}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"outlayer/item\",[\"eventEmitter/EventEmitter\",\"get-size/get-size\",\"get-style-property/get-style-property\",\"fizzy-ui-utils/utils\"],function(c,d,e,f){return b(a,c,d,e,f)}):\"object\"==typeof exports?module.exports=b(a,require(\"wolfy87-eventemitter\"),require(\"get-size\"),require(\"desandro-get-style-property\"),require(\"fizzy-ui-utils\")):(a.Outlayer={},a.Outlayer.Item=b(a,a.EventEmitter,a.getSize,a.getStyleProperty,a.fizzyUIUtils))}(window,function(a,b,c,d,e){\"use strict\";function f(a){for(var b in a)return!1;return b=null,!0}function g(a,b){a&&(this.element=a,this.layout=b,this.position={x:0,y:0},this._create())}function h(a){return a.replace(/([A-Z])/g,function(a){return\"-\"+a.toLowerCase()})}var i=a.getComputedStyle,j=i?function(a){return i(a,null)}:function(a){return a.currentStyle},k=d(\"transition\"),l=d(\"transform\"),m=k&&l,n=!!d(\"perspective\"),o={WebkitTransition:\"webkitTransitionEnd\",MozTransition:\"transitionend\",OTransition:\"otransitionend\",transition:\"transitionend\"}[k],p=[\"transform\",\"transition\",\"transitionDuration\",\"transitionProperty\"],q=function(){for(var a={},b=0,c=p.length;c>b;b++){var e=p[b],f=d(e);f&&f!==e&&(a[e]=f)}return a}();e.extend(g.prototype,b.prototype),g.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:\"absolute\"})},g.prototype.handleEvent=function(a){var b=\"on\"+a.type;this[b]&&this[b](a)},g.prototype.getSize=function(){this.size=c(this.element)},g.prototype.css=function(a){var b=this.element.style;for(var c in a){var d=q[c]||c;b[d]=a[c]}},g.prototype.getPosition=function(){var a=j(this.element),b=this.layout.options,c=b.isOriginLeft,d=b.isOriginTop,e=a[c?\"left\":\"right\"],f=a[d?\"top\":\"bottom\"],g=this.layout.size,h=-1!=e.indexOf(\"%\")?parseFloat(e)/100*g.width:parseInt(e,10),i=-1!=f.indexOf(\"%\")?parseFloat(f)/100*g.height:parseInt(f,10);h=isNaN(h)?0:h,i=isNaN(i)?0:i,h-=c?g.paddingLeft:g.paddingRight,i-=d?g.paddingTop:g.paddingBottom,this.position.x=h,this.position.y=i},g.prototype.layoutPosition=function(){var a=this.layout.size,b=this.layout.options,c={},d=b.isOriginLeft?\"paddingLeft\":\"paddingRight\",e=b.isOriginLeft?\"left\":\"right\",f=b.isOriginLeft?\"right\":\"left\",g=this.position.x+a[d];c[e]=this.getXValue(g),c[f]=\"\";var h=b.isOriginTop?\"paddingTop\":\"paddingBottom\",i=b.isOriginTop?\"top\":\"bottom\",j=b.isOriginTop?\"bottom\":\"top\",k=this.position.y+a[h];c[i]=this.getYValue(k),c[j]=\"\",this.css(c),this.emitEvent(\"layout\",[this])},g.prototype.getXValue=function(a){var b=this.layout.options;return b.percentPosition&&!b.isHorizontal?a/this.layout.size.width*100+\"%\":a+\"px\"},g.prototype.getYValue=function(a){var b=this.layout.options;return b.percentPosition&&b.isHorizontal?a/this.layout.size.height*100+\"%\":a+\"px\"},g.prototype._transitionTo=function(a,b){this.getPosition();var c=this.position.x,d=this.position.y,e=parseInt(a,10),f=parseInt(b,10),g=e===this.position.x&&f===this.position.y;if(this.setPosition(a,b),g&&!this.isTransitioning)return void this.layoutPosition();var h=a-c,i=b-d,j={};j.transform=this.getTranslate(h,i),this.transition({to:j,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},g.prototype.getTranslate=function(a,b){var c=this.layout.options;return a=c.isOriginLeft?a:-a,b=c.isOriginTop?b:-b,n?\"translate3d(\"+a+\"px, \"+b+\"px, 0)\":\"translate(\"+a+\"px, \"+b+\"px)\"},g.prototype.goTo=function(a,b){this.setPosition(a,b),this.layoutPosition()},g.prototype.moveTo=m?g.prototype._transitionTo:g.prototype.goTo,g.prototype.setPosition=function(a,b){this.position.x=parseInt(a,10),this.position.y=parseInt(b,10)},g.prototype._nonTransition=function(a){this.css(a.to),a.isCleaning&&this._removeStyles(a.to);for(var b in a.onTransitionEnd)a.onTransitionEnd[b].call(this)},g.prototype._transition=function(a){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(a);var b=this._transn;for(var c in a.onTransitionEnd)b.onEnd[c]=a.onTransitionEnd[c];for(c in a.to)b.ingProperties[c]=!0,a.isCleaning&&(b.clean[c]=!0);if(a.from){this.css(a.from);var d=this.element.offsetHeight;d=null}this.enableTransition(a.to),this.css(a.to),this.isTransitioning=!0};var r=\"opacity,\"+h(q.transform||\"transform\");g.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:r,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(o,this,!1))},g.prototype.transition=g.prototype[k?\"_transition\":\"_nonTransition\"],g.prototype.onwebkitTransitionEnd=function(a){this.ontransitionend(a)},g.prototype.onotransitionend=function(a){this.ontransitionend(a)};var s={\"-webkit-transform\":\"transform\",\"-moz-transform\":\"transform\",\"-o-transform\":\"transform\"};g.prototype.ontransitionend=function(a){if(a.target===this.element){var b=this._transn,c=s[a.propertyName]||a.propertyName;if(delete b.ingProperties[c],f(b.ingProperties)&&this.disableTransition(),c in b.clean&&(this.element.style[a.propertyName]=\"\",delete b.clean[c]),c in b.onEnd){var d=b.onEnd[c];d.call(this),delete b.onEnd[c]}this.emitEvent(\"transitionEnd\",[this])}},g.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(o,this,!1),this.isTransitioning=!1},g.prototype._removeStyles=function(a){var b={};for(var c in a)b[c]=\"\";this.css(b)};var t={transitionProperty:\"\",transitionDuration:\"\"};return g.prototype.removeTransitionStyles=function(){this.css(t)},g.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:\"\"}),this.emitEvent(\"remove\",[this])},g.prototype.remove=function(){if(!k||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var a=this;this.once(\"transitionEnd\",function(){a.removeElem()}),this.hide()},g.prototype.reveal=function(){delete this.isHidden,this.css({display:\"\"});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty(\"visibleStyle\");b[c]=this.onRevealTransitionEnd,this.transition({from:a.hiddenStyle,to:a.visibleStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent(\"reveal\")},g.prototype.getHideRevealTransitionEndProperty=function(a){var b=this.layout.options[a];if(b.opacity)return\"opacity\";for(var c in b)return c},g.prototype.hide=function(){this.isHidden=!0,this.css({display:\"\"});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty(\"hiddenStyle\");b[c]=this.onHideTransitionEnd,this.transition({from:a.visibleStyle,to:a.hiddenStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:\"none\"}),this.emitEvent(\"hide\"))},g.prototype.destroy=function(){this.css({position:\"\",left:\"\",right:\"\",top:\"\",bottom:\"\",transition:\"\",transform:\"\"})},g}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"outlayer/outlayer\",[\"eventie/eventie\",\"eventEmitter/EventEmitter\",\"get-size/get-size\",\"fizzy-ui-utils/utils\",\"./item\"],function(c,d,e,f,g){return b(a,c,d,e,f,g)}):\"object\"==typeof exports?module.exports=b(a,require(\"eventie\"),require(\"wolfy87-eventemitter\"),require(\"get-size\"),require(\"fizzy-ui-utils\"),require(\"./item\")):a.Outlayer=b(a,a.eventie,a.EventEmitter,a.getSize,a.fizzyUIUtils,a.Outlayer.Item)}(window,function(a,b,c,d,e,f){\"use strict\";function g(a,b){var c=e.getQueryElement(a);if(!c)return void(h&&h.error(\"Bad element for \"+this.constructor.namespace+\": \"+(c||a)));this.element=c,i&&(this.$element=i(this.element)),this.options=e.extend({},this.constructor.defaults),this.option(b);var d=++k;this.element.outlayerGUID=d,l[d]=this,this._create(),this.options.isInitLayout&&this.layout()}var h=a.console,i=a.jQuery,j=function(){},k=0,l={};return g.namespace=\"outlayer\",g.Item=f,g.defaults={containerStyle:{position:\"relative\"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:\"0.4s\",hiddenStyle:{opacity:0,transform:\"scale(0.001)\"},visibleStyle:{opacity:1,transform:\"scale(1)\"}},e.extend(g.prototype,c.prototype),g.prototype.option=function(a){e.extend(this.options,a)},g.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),e.extend(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},g.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},g.prototype._itemize=function(a){for(var b=this._filterFindItemElements(a),c=this.constructor.Item,d=[],e=0,f=b.length;f>e;e++){var g=b[e],h=new c(g,this);d.push(h)}return d},g.prototype._filterFindItemElements=function(a){return e.filterFindElements(a,this.options.itemSelector)},g.prototype.getItemElements=function(){for(var a=[],b=0,c=this.items.length;c>b;b++)a.push(this.items[b].element);return a},g.prototype.layout=function(){this._resetLayout(),this._manageStamps();var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,a),this._isLayoutInited=!0},g.prototype._init=g.prototype.layout,g.prototype._resetLayout=function(){this.getSize()},g.prototype.getSize=function(){this.size=d(this.element)},g.prototype._getMeasurement=function(a,b){var c,f=this.options[a];f?(\"string\"==typeof f?c=this.element.querySelector(f):e.isElement(f)&&(c=f),this[a]=c?d(c)[b]:f):this[a]=0},g.prototype.layoutItems=function(a,b){a=this._getItemsForLayout(a),this._layoutItems(a,b),this._postLayout()},g.prototype._getItemsForLayout=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];e.isIgnored||b.push(e)}return b},g.prototype._layoutItems=function(a,b){if(this._emitCompleteOnItems(\"layout\",a),a&&a.length){for(var c=[],d=0,e=a.length;e>d;d++){var f=a[d],g=this._getItemLayoutPosition(f);g.item=f,g.isInstant=b||f.isLayoutInstant,c.push(g)}this._processLayoutQueue(c)}},g.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},g.prototype._processLayoutQueue=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];this._positionItem(d.item,d.x,d.y,d.isInstant)}},g.prototype._positionItem=function(a,b,c,d){d?a.goTo(b,c):a.moveTo(b,c)},g.prototype._postLayout=function(){this.resizeContainer()},g.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var a=this._getContainerSize();a&&(this._setContainerMeasure(a.width,!0),this._setContainerMeasure(a.height,!1))}},g.prototype._getContainerSize=j,g.prototype._setContainerMeasure=function(a,b){if(void 0!==a){var c=this.size;c.isBorderBox&&(a+=b?c.paddingLeft+c.paddingRight+c.borderLeftWidth+c.borderRightWidth:c.paddingBottom+c.paddingTop+c.borderTopWidth+c.borderBottomWidth),a=Math.max(a,0),this.element.style[b?\"width\":\"height\"]=a+\"px\"}},g.prototype._emitCompleteOnItems=function(a,b){function c(){e.dispatchEvent(a+\"Complete\",null,[b])}function d(){g++,g===f&&c()}var e=this,f=b.length;if(!b||!f)return void c();for(var g=0,h=0,i=b.length;i>h;h++){var j=b[h];j.once(a,d)}},g.prototype.dispatchEvent=function(a,b,c){var d=b?[b].concat(c):c;if(this.emitEvent(a,d),i)if(this.$element=this.$element||i(this.element),b){var e=i.Event(b);e.type=a,this.$element.trigger(e,c)}else this.$element.trigger(a,c)},g.prototype.ignore=function(a){var b=this.getItem(a);b&&(b.isIgnored=!0)},g.prototype.unignore=function(a){var b=this.getItem(a);b&&delete b.isIgnored},g.prototype.stamp=function(a){if(a=this._find(a)){this.stamps=this.stamps.concat(a);for(var b=0,c=a.length;c>b;b++){var d=a[b];this.ignore(d)}}},g.prototype.unstamp=function(a){if(a=this._find(a))for(var b=0,c=a.length;c>b;b++){var d=a[b];e.removeFrom(this.stamps,d),this.unignore(d)}},g.prototype._find=function(a){return a?(\"string\"==typeof a&&(a=this.element.querySelectorAll(a)),a=e.makeArray(a)):void 0},g.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var a=0,b=this.stamps.length;b>a;a++){var c=this.stamps[a];this._manageStamp(c)}}},g.prototype._getBoundingRect=function(){var a=this.element.getBoundingClientRect(),b=this.size;this._boundingRect={left:a.left+b.paddingLeft+b.borderLeftWidth,top:a.top+b.paddingTop+b.borderTopWidth,right:a.right-(b.paddingRight+b.borderRightWidth),bottom:a.bottom-(b.paddingBottom+b.borderBottomWidth)}},g.prototype._manageStamp=j,g.prototype._getElementOffset=function(a){var b=a.getBoundingClientRect(),c=this._boundingRect,e=d(a),f={left:b.left-c.left-e.marginLeft,top:b.top-c.top-e.marginTop,right:c.right-b.right-e.marginRight,bottom:c.bottom-b.bottom-e.marginBottom};return f},g.prototype.handleEvent=function(a){var b=\"on\"+a.type;this[b]&&this[b](a)},g.prototype.bindResize=function(){this.isResizeBound||(b.bind(a,\"resize\",this),this.isResizeBound=!0)},g.prototype.unbindResize=function(){this.isResizeBound&&b.unbind(a,\"resize\",this),this.isResizeBound=!1},g.prototype.onresize=function(){function a(){b.resize(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},g.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},g.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a;return b&&a.innerWidth!==this.size.innerWidth},g.prototype.addItems=function(a){var b=this._itemize(a);return b.length&&(this.items=this.items.concat(b)),b},g.prototype.appended=function(a){var b=this.addItems(a);b.length&&(this.layoutItems(b,!0),this.reveal(b))},g.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){var c=this.items.slice(0);this.items=b.concat(c),this._resetLayout(),this._manageStamps(),this.layoutItems(b,!0),this.reveal(b),this.layoutItems(c)}},g.prototype.reveal=function(a){this._emitCompleteOnItems(\"reveal\",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.reveal()}},g.prototype.hide=function(a){this._emitCompleteOnItems(\"hide\",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.hide()}},g.prototype.revealItemElements=function(a){var b=this.getItems(a);this.reveal(b)},g.prototype.hideItemElements=function(a){var b=this.getItems(a);this.hide(b)},g.prototype.getItem=function(a){for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];if(d.element===a)return d}},g.prototype.getItems=function(a){a=e.makeArray(a);for(var b=[],c=0,d=a.length;d>c;c++){var f=a[c],g=this.getItem(f);g&&b.push(g)}return b},g.prototype.remove=function(a){var b=this.getItems(a);if(this._emitCompleteOnItems(\"remove\",b),b&&b.length)for(var c=0,d=b.length;d>c;c++){var f=b[c];f.remove(),e.removeFrom(this.items,f)}},g.prototype.destroy=function(){var a=this.element.style;a.height=\"\",a.position=\"\",a.width=\"\";for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];d.destroy()}this.unbindResize();var e=this.element.outlayerGUID;delete l[e],delete this.element.outlayerGUID,i&&i.removeData(this.element,this.constructor.namespace)},g.data=function(a){a=e.getQueryElement(a);var b=a&&a.outlayerGUID;return b&&l[b]},g.create=function(a,b){function c(){g.apply(this,arguments)}return Object.create?c.prototype=Object.create(g.prototype):e.extend(c.prototype,g.prototype),c.prototype.constructor=c,c.defaults=e.extend({},g.defaults),e.extend(c.defaults,b),c.prototype.settings={},c.namespace=a,c.data=g.data,c.Item=function(){f.apply(this,arguments)},c.Item.prototype=new f,e.htmlInit(c,a),i&&i.bridget&&i.bridget(a,c),c},g.Item=f,g}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"isotope/js/item\",[\"outlayer/outlayer\"],b):\"object\"==typeof exports?module.exports=b(require(\"outlayer\")):(a.Isotope=a.Isotope||{},a.Isotope.Item=b(a.Outlayer))}(window,function(a){\"use strict\";function b(){a.Item.apply(this,arguments)}b.prototype=new a.Item,b.prototype._create=function(){this.id=this.layout.itemGUID++,a.Item.prototype._create.call(this),this.sortData={}},b.prototype.updateSortData=function(){if(!this.isIgnored){this.sortData.id=this.id,this.sortData[\"original-order\"]=this.id,this.sortData.random=Math.random();var a=this.layout.options.getSortData,b=this.layout._sorters;for(var c in a){var d=b[c];this.sortData[c]=d(this.element,this)}}};var c=b.prototype.destroy;return b.prototype.destroy=function(){c.apply(this,arguments),this.css({display:\"\"})},b}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"isotope/js/layout-mode\",[\"get-size/get-size\",\"outlayer/outlayer\"],b):\"object\"==typeof exports?module.exports=b(require(\"get-size\"),require(\"outlayer\")):(a.Isotope=a.Isotope||{},a.Isotope.LayoutMode=b(a.getSize,a.Outlayer))}(window,function(a,b){\"use strict\";function c(a){this.isotope=a,a&&(this.options=a.options[this.namespace],this.element=a.element,this.items=a.filteredItems,this.size=a.size)}return function(){function a(a){return function(){return b.prototype[a].apply(this.isotope,arguments)}}for(var d=[\"_resetLayout\",\"_getItemLayoutPosition\",\"_manageStamp\",\"_getContainerSize\",\"_getElementOffset\",\"needsResizeLayout\"],e=0,f=d.length;f>e;e++){var g=d[e];c.prototype[g]=a(g)}}(),c.prototype.needsVerticalResizeLayout=function(){var b=a(this.isotope.element),c=this.isotope.size&&b;return c&&b.innerHeight!=this.isotope.size.innerHeight},c.prototype._getMeasurement=function(){this.isotope._getMeasurement.apply(this,arguments)},c.prototype.getColumnWidth=function(){this.getSegmentSize(\"column\",\"Width\")},c.prototype.getRowHeight=function(){this.getSegmentSize(\"row\",\"Height\")},c.prototype.getSegmentSize=function(a,b){var c=a+b,d=\"outer\"+b;if(this._getMeasurement(c,d),!this[c]){var e=this.getFirstItemSize();this[c]=e&&e[d]||this.isotope.size[\"inner\"+b]}},c.prototype.getFirstItemSize=function(){var b=this.isotope.filteredItems[0];return b&&b.element&&a(b.element)},c.prototype.layout=function(){this.isotope.layout.apply(this.isotope,arguments)},c.prototype.getSize=function(){this.isotope.getSize(),this.size=this.isotope.size},c.modes={},c.create=function(a,b){function d(){c.apply(this,arguments)}return d.prototype=new c,b&&(d.options=b),d.prototype.namespace=a,c.modes[a]=d,d},c}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"masonry/masonry\",[\"outlayer/outlayer\",\"get-size/get-size\",\"fizzy-ui-utils/utils\"],b):\"object\"==typeof exports?module.exports=b(require(\"outlayer\"),require(\"get-size\"),require(\"fizzy-ui-utils\")):a.Masonry=b(a.Outlayer,a.getSize,a.fizzyUIUtils)}(window,function(a,b,c){var d=a.create(\"masonry\");return d.prototype._resetLayout=function(){this.getSize(),this._getMeasurement(\"columnWidth\",\"outerWidth\"),this._getMeasurement(\"gutter\",\"outerWidth\"),this.measureColumns();var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0);this.maxY=0},d.prototype.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var a=this.items[0],c=a&&a.element;this.columnWidth=c&&b(c).outerWidth||this.containerWidth}var d=this.columnWidth+=this.gutter,e=this.containerWidth+this.gutter,f=e/d,g=d-e%d,h=g&&1>g?\"round\":\"floor\";f=Math[h](f),this.cols=Math.max(f,1)},d.prototype.getContainerWidth=function(){var a=this.options.isFitWidth?this.element.parentNode:this.element,c=b(a);this.containerWidth=c&&c.innerWidth},d.prototype._getItemLayoutPosition=function(a){a.getSize();var b=a.size.outerWidth%this.columnWidth,d=b&&1>b?\"round\":\"ceil\",e=Math[d](a.size.outerWidth/this.columnWidth);e=Math.min(e,this.cols);for(var f=this._getColGroup(e),g=Math.min.apply(Math,f),h=c.indexOf(f,g),i={x:this.columnWidth*h,y:g},j=g+a.size.outerHeight,k=this.cols+1-f.length,l=0;k>l;l++)this.colYs[h+l]=j;return i},d.prototype._getColGroup=function(a){if(2>a)return this.colYs;for(var b=[],c=this.cols+1-a,d=0;c>d;d++){var e=this.colYs.slice(d,d+a);b[d]=Math.max.apply(Math,e)}return b},d.prototype._manageStamp=function(a){var c=b(a),d=this._getElementOffset(a),e=this.options.isOriginLeft?d.left:d.right,f=e+c.outerWidth,g=Math.floor(e/this.columnWidth);g=Math.max(0,g);var h=Math.floor(f/this.columnWidth);h-=f%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var i=(this.options.isOriginTop?d.top:d.bottom)+c.outerHeight,j=g;h>=j;j++)this.colYs[j]=Math.max(i,this.colYs[j])},d.prototype._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var a={height:this.maxY};return this.options.isFitWidth&&(a.width=this._getContainerFitWidth()),a},d.prototype._getContainerFitWidth=function(){for(var a=0,b=this.cols;--b&&0===this.colYs[b];)a++;return(this.cols-a)*this.columnWidth-this.gutter},d.prototype.needsResizeLayout=function(){var a=this.containerWidth;return this.getContainerWidth(),a!==this.containerWidth},d}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"isotope/js/layout-modes/masonry\",[\"../layout-mode\",\"masonry/masonry\"],b):\"object\"==typeof exports?module.exports=b(require(\"../layout-mode\"),require(\"masonry-layout\")):b(a.Isotope.LayoutMode,a.Masonry)}(window,function(a,b){\"use strict\";function c(a,b){for(var c in b)a[c]=b[c];return a}var d=a.create(\"masonry\"),e=d.prototype._getElementOffset,f=d.prototype.layout,g=d.prototype._getMeasurement;\r\nc(d.prototype,b.prototype),d.prototype._getElementOffset=e,d.prototype.layout=f,d.prototype._getMeasurement=g;var h=d.prototype.measureColumns;d.prototype.measureColumns=function(){this.items=this.isotope.filteredItems,h.call(this)};var i=d.prototype._manageStamp;return d.prototype._manageStamp=function(){this.options.isOriginLeft=this.isotope.options.isOriginLeft,this.options.isOriginTop=this.isotope.options.isOriginTop,i.apply(this,arguments)},d}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"isotope/js/layout-modes/fit-rows\",[\"../layout-mode\"],b):\"object\"==typeof exports?module.exports=b(require(\"../layout-mode\")):b(a.Isotope.LayoutMode)}(window,function(a){\"use strict\";var b=a.create(\"fitRows\");return b.prototype._resetLayout=function(){this.x=0,this.y=0,this.maxY=0,this._getMeasurement(\"gutter\",\"outerWidth\")},b.prototype._getItemLayoutPosition=function(a){a.getSize();var b=a.size.outerWidth+this.gutter,c=this.isotope.size.innerWidth+this.gutter;0!==this.x&&b+this.x>c&&(this.x=0,this.y=this.maxY);var d={x:this.x,y:this.y};return this.maxY=Math.max(this.maxY,this.y+a.size.outerHeight),this.x+=b,d},b.prototype._getContainerSize=function(){return{height:this.maxY}},b}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define(\"isotope/js/layout-modes/vertical\",[\"../layout-mode\"],b):\"object\"==typeof exports?module.exports=b(require(\"../layout-mode\")):b(a.Isotope.LayoutMode)}(window,function(a){\"use strict\";var b=a.create(\"vertical\",{horizontalAlignment:0});return b.prototype._resetLayout=function(){this.y=0},b.prototype._getItemLayoutPosition=function(a){a.getSize();var b=(this.isotope.size.innerWidth-a.size.outerWidth)*this.options.horizontalAlignment,c=this.y;return this.y+=a.size.outerHeight,{x:b,y:c}},b.prototype._getContainerSize=function(){return{height:this.y}},b}),function(a,b){\"use strict\";\"function\"==typeof define&&define.amd?define([\"outlayer/outlayer\",\"get-size/get-size\",\"matches-selector/matches-selector\",\"fizzy-ui-utils/utils\",\"isotope/js/item\",\"isotope/js/layout-mode\",\"isotope/js/layout-modes/masonry\",\"isotope/js/layout-modes/fit-rows\",\"isotope/js/layout-modes/vertical\"],function(c,d,e,f,g,h){return b(a,c,d,e,f,g,h)}):\"object\"==typeof exports?module.exports=b(a,require(\"outlayer\"),require(\"get-size\"),require(\"desandro-matches-selector\"),require(\"fizzy-ui-utils\"),require(\"./item\"),require(\"./layout-mode\"),require(\"./layout-modes/masonry\"),require(\"./layout-modes/fit-rows\"),require(\"./layout-modes/vertical\")):a.Isotope=b(a,a.Outlayer,a.getSize,a.matchesSelector,a.fizzyUIUtils,a.Isotope.Item,a.Isotope.LayoutMode)}(window,function(a,b,c,d,e,f,g){function h(a,b){return function(c,d){for(var e=0,f=a.length;f>e;e++){var g=a[e],h=c.sortData[g],i=d.sortData[g];if(h>i||i>h){var j=void 0!==b[g]?b[g]:b,k=j?1:-1;return(h>i?1:-1)*k}}return 0}}var i=a.jQuery,j=String.prototype.trim?function(a){return a.trim()}:function(a){return a.replace(/^\\s+|\\s+$/g,\"\")},k=document.documentElement,l=k.textContent?function(a){return a.textContent}:function(a){return a.innerText},m=b.create(\"isotope\",{layoutMode:\"masonry\",isJQueryFiltering:!0,sortAscending:!0});m.Item=f,m.LayoutMode=g,m.prototype._create=function(){this.itemGUID=0,this._sorters={},this._getSorters(),b.prototype._create.call(this),this.modes={},this.filteredItems=this.items,this.sortHistory=[\"original-order\"];for(var a in g.modes)this._initLayoutMode(a)},m.prototype.reloadItems=function(){this.itemGUID=0,b.prototype.reloadItems.call(this)},m.prototype._itemize=function(){for(var a=b.prototype._itemize.apply(this,arguments),c=0,d=a.length;d>c;c++){var e=a[c];e.id=this.itemGUID++}return this._updateItemsSortData(a),a},m.prototype._initLayoutMode=function(a){var b=g.modes[a],c=this.options[a]||{};this.options[a]=b.options?e.extend(b.options,c):c,this.modes[a]=new b(this)},m.prototype.layout=function(){return!this._isLayoutInited&&this.options.isInitLayout?void this.arrange():void this._layout()},m.prototype._layout=function(){var a=this._getIsInstant();this._resetLayout(),this._manageStamps(),this.layoutItems(this.filteredItems,a),this._isLayoutInited=!0},m.prototype.arrange=function(a){function b(){d.reveal(c.needReveal),d.hide(c.needHide)}this.option(a),this._getIsInstant();var c=this._filter(this.items);this.filteredItems=c.matches;var d=this;this._bindArrangeComplete(),this._isInstant?this._noTransition(b):b(),this._sort(),this._layout()},m.prototype._init=m.prototype.arrange,m.prototype._getIsInstant=function(){var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;return this._isInstant=a,a},m.prototype._bindArrangeComplete=function(){function a(){b&&c&&d&&e.dispatchEvent(\"arrangeComplete\",null,[e.filteredItems])}var b,c,d,e=this;this.once(\"layoutComplete\",function(){b=!0,a()}),this.once(\"hideComplete\",function(){c=!0,a()}),this.once(\"revealComplete\",function(){d=!0,a()})},m.prototype._filter=function(a){var b=this.options.filter;b=b||\"*\";for(var c=[],d=[],e=[],f=this._getFilterTest(b),g=0,h=a.length;h>g;g++){var i=a[g];if(!i.isIgnored){var j=f(i);j&&c.push(i),j&&i.isHidden?d.push(i):j||i.isHidden||e.push(i)}}return{matches:c,needReveal:d,needHide:e}},m.prototype._getFilterTest=function(a){return i&&this.options.isJQueryFiltering?function(b){return i(b.element).is(a)}:\"function\"==typeof a?function(b){return a(b.element)}:function(b){return d(b.element,a)}},m.prototype.updateSortData=function(a){var b;a?(a=e.makeArray(a),b=this.getItems(a)):b=this.items,this._getSorters(),this._updateItemsSortData(b)},m.prototype._getSorters=function(){var a=this.options.getSortData;for(var b in a){var c=a[b];this._sorters[b]=n(c)}},m.prototype._updateItemsSortData=function(a){for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.updateSortData()}};var n=function(){function a(a){if(\"string\"!=typeof a)return a;var c=j(a).split(\" \"),d=c[0],e=d.match(/^\\[(.+)\\]$/),f=e&&e[1],g=b(f,d),h=m.sortDataParsers[c[1]];return a=h?function(a){return a&&h(g(a))}:function(a){return a&&g(a)}}function b(a,b){var c;return c=a?function(b){return b.getAttribute(a)}:function(a){var c=a.querySelector(b);return c&&l(c)}}return a}();m.sortDataParsers={parseInt:function(a){return parseInt(a,10)},parseFloat:function(a){return parseFloat(a)}},m.prototype._sort=function(){var a=this.options.sortBy;if(a){var b=[].concat.apply(a,this.sortHistory),c=h(b,this.options.sortAscending);this.filteredItems.sort(c),a!=this.sortHistory[0]&&this.sortHistory.unshift(a)}},m.prototype._mode=function(){var a=this.options.layoutMode,b=this.modes[a];if(!b)throw new Error(\"No layout mode: \"+a);return b.options=this.options[a],b},m.prototype._resetLayout=function(){b.prototype._resetLayout.call(this),this._mode()._resetLayout()},m.prototype._getItemLayoutPosition=function(a){return this._mode()._getItemLayoutPosition(a)},m.prototype._manageStamp=function(a){this._mode()._manageStamp(a)},m.prototype._getContainerSize=function(){return this._mode()._getContainerSize()},m.prototype.needsResizeLayout=function(){return this._mode().needsResizeLayout()},m.prototype.appended=function(a){var b=this.addItems(a);if(b.length){var c=this._filterRevealAdded(b);this.filteredItems=this.filteredItems.concat(c)}},m.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){this._resetLayout(),this._manageStamps();var c=this._filterRevealAdded(b);this.layoutItems(this.filteredItems),this.filteredItems=c.concat(this.filteredItems),this.items=b.concat(this.items)}},m.prototype._filterRevealAdded=function(a){var b=this._filter(a);return this.hide(b.needHide),this.reveal(b.matches),this.layoutItems(b.matches,!0),b.matches},m.prototype.insert=function(a){var b=this.addItems(a);if(b.length){var c,d,e=b.length;for(c=0;e>c;c++)d=b[c],this.element.appendChild(d.element);var f=this._filter(b).matches;for(c=0;e>c;c++)b[c].isLayoutInstant=!0;for(this.arrange(),c=0;e>c;c++)delete b[c].isLayoutInstant;this.reveal(f)}};var o=m.prototype.remove;return m.prototype.remove=function(a){a=e.makeArray(a);var b=this.getItems(a);o.call(this,a);var c=b&&b.length;if(c)for(var d=0;c>d;d++){var f=b[d];e.removeFrom(this.filteredItems,f)}},m.prototype.shuffle=function(){for(var a=0,b=this.items.length;b>a;a++){var c=this.items[a];c.sortData.random=Math.random()}this.options.sortBy=\"random\",this._sort(),this._layout()},m.prototype._noTransition=function(a){var b=this.options.transitionDuration;this.options.transitionDuration=0;var c=a.call(this);return this.options.transitionDuration=b,c},m.prototype.getFilteredItemElements=function(){for(var a=[],b=0,c=this.filteredItems.length;c>b;b++)a.push(this.filteredItems[b].element);return a},m});\r\n\r\n\r\n\r\n/*!\r\n* jquery.counterup.js 1.0\r\n*\r\n* Copyright 2013, Benjamin Intal http://gambit.ph @bfintal\r\n* Released under the GPL v2 License\r\n*\r\n* Date: Nov 26, 2013\r\n*/(function(e){\"use strict\";e.fn.counterUp=function(t){var n=e.extend({time:400,delay:10},t);return this.each(function(){var t=e(this),r=n,i=function(){var e=[],n=r.time/r.delay,i=t.text(),s=/[0-9]+,[0-9]+/.test(i);i=i.replace(/,/g,\"\");var o=/^[0-9]+$/.test(i),u=/^[0-9]+\\.[0-9]+$/.test(i),a=u?(i.split(\".\")[1]||[]).length:0;for(var f=n;f>=1;f--){var l=parseInt(i/n*f);u&&(l=parseFloat(i/n*f).toFixed(a));if(s)while(/(\\d+)(\\d{3})/.test(l.toString()))l=l.toString().replace(/(\\d+)(\\d{3})/,\"$1,$2\");e.unshift(l)}t.data(\"counterup-nums\",e);t.text(\"0\");var c=function(){t.text(t.data(\"counterup-nums\").shift());if(t.data(\"counterup-nums\").length)setTimeout(t.data(\"counterup-func\"),r.delay);else{delete t.data(\"counterup-nums\");t.data(\"counterup-nums\",null);t.data(\"counterup-func\",null)}};t.data(\"counterup-func\",c);setTimeout(t.data(\"counterup-func\"),r.delay)};t.waypoint(i,{offset:\"100%\",triggerOnce:!0})})}})(jQuery);\r\n\r\n\r\n\r\n/*\r\n * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/\r\n *\r\n * Uses the built in easing capabilities added In jQuery 1.1\r\n * to offer multiple easing options\r\n *\r\n * TERMS OF USE - EASING EQUATIONS\r\n * \r\n * Open source under the BSD License. \r\n * \r\n * Copyright © 2001 Robert Penner\r\n * All rights reserved.\r\n *\r\n * TERMS OF USE - jQuery Easing\r\n * \r\n * Open source under the BSD License. \r\n * \r\n * Copyright © 2008 George McGinley Smith\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification, \r\n * are permitted provided that the following conditions are met:\r\n * \r\n * Redistributions of source code must retain the above copyright notice, this list of \r\n * conditions and the following disclaimer.\r\n * Redistributions in binary form must reproduce the above copyright notice, this list \r\n * of conditions and the following disclaimer in the documentation and/or other materials \r\n * provided with the distribution.\r\n * \r\n * Neither the name of the author nor the names of contributors may be used to endorse \r\n * or promote products derived from this software without specific prior written permission.\r\n * \r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY \r\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r\n * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r\n *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r\n *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED \r\n * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED \r\n * OF THE POSSIBILITY OF SUCH DAMAGE. \r\n *\r\n*/\r\njQuery.easing.jswing=jQuery.easing.swing;jQuery.extend(jQuery.easing,{def:\"easeOutQuad\",swing:function(e,f,a,h,g){return jQuery.easing[jQuery.easing.def](e,f,a,h,g)},easeInQuad:function(e,f,a,h,g){return h*(f/=g)*f+a},easeOutQuad:function(e,f,a,h,g){return -h*(f/=g)*(f-2)+a},easeInOutQuad:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f+a}return -h/2*((--f)*(f-2)-1)+a},easeInCubic:function(e,f,a,h,g){return h*(f/=g)*f*f+a},easeOutCubic:function(e,f,a,h,g){return h*((f=f/g-1)*f*f+1)+a},easeInOutCubic:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f+a}return h/2*((f-=2)*f*f+2)+a},easeInQuart:function(e,f,a,h,g){return h*(f/=g)*f*f*f+a},easeOutQuart:function(e,f,a,h,g){return -h*((f=f/g-1)*f*f*f-1)+a},easeInOutQuart:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f+a}return -h/2*((f-=2)*f*f*f-2)+a},easeInQuint:function(e,f,a,h,g){return h*(f/=g)*f*f*f*f+a},easeOutQuint:function(e,f,a,h,g){return h*((f=f/g-1)*f*f*f*f+1)+a},easeInOutQuint:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f*f+a}return h/2*((f-=2)*f*f*f*f+2)+a},easeInSine:function(e,f,a,h,g){return -h*Math.cos(f/g*(Math.PI/2))+h+a},easeOutSine:function(e,f,a,h,g){return h*Math.sin(f/g*(Math.PI/2))+a},easeInOutSine:function(e,f,a,h,g){return -h/2*(Math.cos(Math.PI*f/g)-1)+a},easeInExpo:function(e,f,a,h,g){return(f==0)?a:h*Math.pow(2,10*(f/g-1))+a},easeOutExpo:function(e,f,a,h,g){return(f==g)?a+h:h*(-Math.pow(2,-10*f/g)+1)+a},easeInOutExpo:function(e,f,a,h,g){if(f==0){return a}if(f==g){return a+h}if((f/=g/2)<1){return h/2*Math.pow(2,10*(f-1))+a}return h/2*(-Math.pow(2,-10*--f)+2)+a},easeInCirc:function(e,f,a,h,g){return -h*(Math.sqrt(1-(f/=g)*f)-1)+a},easeOutCirc:function(e,f,a,h,g){return h*Math.sqrt(1-(f=f/g-1)*f)+a},easeInOutCirc:function(e,f,a,h,g){if((f/=g/2)<1){return -h/2*(Math.sqrt(1-f*f)-1)+a}return h/2*(Math.sqrt(1-(f-=2)*f)+1)+a},easeInElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return -(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e},easeOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return g*Math.pow(2,-10*h)*Math.sin((h*k-i)*(2*Math.PI)/j)+l+e},easeInOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k/2)==2){return e+l}if(!j){j=k*(0.3*1.5)}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}if(h<1){return -0.5*(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e}return g*Math.pow(2,-10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j)*0.5+l+e},easeInBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*(f/=h)*f*((g+1)*f-g)+a},easeOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*((f=f/h-1)*f*((g+1)*f+g)+1)+a},easeInOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}if((f/=h/2)<1){return i/2*(f*f*(((g*=(1.525))+1)*f-g))+a}return i/2*((f-=2)*f*(((g*=(1.525))+1)*f+g)+2)+a},easeInBounce:function(e,f,a,h,g){return h-jQuery.easing.easeOutBounce(e,g-f,0,h,g)+a},easeOutBounce:function(e,f,a,h,g){if((f/=g)<(1/2.75)){return h*(7.5625*f*f)+a}else{if(f<(2/2.75)){return h*(7.5625*(f-=(1.5/2.75))*f+0.75)+a}else{if(f<(2.5/2.75)){return h*(7.5625*(f-=(2.25/2.75))*f+0.9375)+a}else{return h*(7.5625*(f-=(2.625/2.75))*f+0.984375)+a}}}},easeInOutBounce:function(e,f,a,h,g){if(f<g/2){return jQuery.easing.easeInBounce(e,f*2,0,h,g)*0.5+a}return jQuery.easing.easeOutBounce(e,f*2-g,0,h,g)*0.5+h*0.5+a}});\r\n\r\n\r\n\r\n\r\n\r\n// CountDown Clock\r\n// Version   : 1.0.1\r\n// Developer : Ekrem KAYA\r\n// Website   : http://e-piksel.com\r\n// GitHub    : https://github.com/epiksel/countdown\r\n\r\n!function(t){t.fn.countdown=function(e,n){function o(){var t=new Date(r.date),e=s(),o=t-e;if(0>o)return clearInterval(d),void(n&&\"function\"==typeof n&&n());var a=1e3,f=60*a,u=60*f,l=24*u,c=Math.floor(o/l),h=Math.floor(o%l/u),x=Math.floor(o%u/f),g=Math.floor(o%f/a),y=1===c?r.day:r.days,m=1===h?r.hour:r.hours,v=1===x?r.minute:r.minutes,D=1===g?r.second:r.seconds;c=String(c).length>=2?c:\"0\"+c,h=String(h).length>=2?h:\"0\"+h,x=String(x).length>=2?x:\"0\"+x,g=String(g).length>=2?g:\"0\"+g,i.find(\".days\").text(c),i.find(\".hours\").text(h),i.find(\".minutes\").text(x),i.find(\".seconds\").text(g),i.find(\".days_text\").text(y),i.find(\".hours_text\").text(m),i.find(\".minutes_text\").text(v),i.find(\".seconds_text\").text(D)}var r=t.extend({date:null,offset:null,day:\"Day\",days:\"Days\",hour:\"Hour\",hours:\"Hours\",minute:\"Minute\",minutes:\"Mins\",second:\"Sec\",seconds:\"Secs\"},e);r.date||t.error(\"Date is not defined.\"),Date.parse(r.date)||t.error(\"Incorrect date format, it should look like this, 12/24/2012 12:00:00.\");var i=this,s=function(){var t=new Date,e=t.getTime()+6e4*t.getTimezoneOffset(),n=new Date(e+36e5*r.offset);return n},d=setInterval(o,1e3)}}(jQuery);"
  },
  {
    "path": "docs/assets/js/validator.js",
    "content": "\r\n/* ========================================================================\r\n * Bootstrap (plugin): validator.js v0.10.2\r\n * ========================================================================\r\n * The MIT License (MIT)\r\n *\r\n * Copyright (c) 2015 Cina Saffary.\r\n * Made by @1000hz in the style of Bootstrap 3 era @fat\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"Software\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n * ======================================================================== */\r\n\r\n\r\n+function ($) {\r\n  'use strict';\r\n\r\n  // VALIDATOR CLASS DEFINITION\r\n  // ==========================\r\n\r\n  function getValue($el) {\r\n    return $el.is('[type=\"checkbox\"]') ? $el.prop('checked')                                     :\r\n           $el.is('[type=\"radio\"]')    ? !!$('[name=\"' + $el.attr('name') + '\"]:checked').length :\r\n                                         $.trim($el.val())\r\n  }\r\n\r\n  var Validator = function (element, options) {\r\n    this.options  = options\r\n    this.$element = $(element)\r\n    this.$inputs  = this.$element.find(Validator.INPUT_SELECTOR)\r\n    this.$btn     = $('button[type=\"submit\"], input[type=\"submit\"]')\r\n                      .filter('[form=\"' + this.$element.attr('id') + '\"]')\r\n                      .add(this.$element.find('input[type=\"submit\"], button[type=\"submit\"]'))\r\n\r\n    options.errors = $.extend({}, Validator.DEFAULTS.errors, options.errors)\r\n\r\n    for (var custom in options.custom) {\r\n      if (!options.errors[custom]) throw new Error('Missing default error message for custom validator: ' + custom)\r\n    }\r\n\r\n    $.extend(Validator.VALIDATORS, options.custom)\r\n\r\n    this.$element.attr('novalidate', true) // disable automatic native validation\r\n    this.toggleSubmit()\r\n\r\n    this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', Validator.INPUT_SELECTOR, $.proxy(this.onInput, this))\r\n    this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))\r\n\r\n    this.$element.find('[data-match]').each(function () {\r\n      var $this  = $(this)\r\n      var target = $this.data('match')\r\n\r\n      $(target).on('input.bs.validator', function (e) {\r\n        getValue($this) && $this.trigger('input.bs.validator')\r\n      })\r\n    })\r\n  }\r\n\r\n  Validator.INPUT_SELECTOR = ':input:not([type=\"submit\"], button):enabled:visible'\r\n\r\n  Validator.FOCUS_OFFSET = 20\r\n\r\n  Validator.DEFAULTS = {\r\n    delay: 500,\r\n    html: false,\r\n    disable: true,\r\n    focus: true,\r\n    custom: {},\r\n    errors: {\r\n      match: 'Does not match',\r\n      minlength: 'Not long enough'\r\n    },\r\n    feedback: {\r\n      success: 'glyphicon-ok',\r\n      error: 'glyphicon-remove'\r\n    }\r\n  }\r\n\r\n  Validator.VALIDATORS = {\r\n    'native': function ($el) {\r\n      var el = $el[0]\r\n      return el.checkValidity ? el.checkValidity() : true\r\n    },\r\n    'match': function ($el) {\r\n      var target = $el.data('match')\r\n      return !$el.val() || $el.val() === $(target).val()\r\n    },\r\n    'minlength': function ($el) {\r\n      var minlength = $el.data('minlength')\r\n      return !$el.val() || $el.val().length >= minlength\r\n    }\r\n  }\r\n\r\n  Validator.prototype.onInput = function (e) {\r\n    var self        = this\r\n    var $el         = $(e.target)\r\n    var deferErrors = e.type !== 'focusout'\r\n    this.validateInput($el, deferErrors).done(function () {\r\n      self.toggleSubmit()\r\n    })\r\n  }\r\n\r\n  Validator.prototype.validateInput = function ($el, deferErrors) {\r\n    var value      = getValue($el)\r\n    var prevValue  = $el.data('bs.validator.previous')\r\n    var prevErrors = $el.data('bs.validator.errors')\r\n    var errors\r\n\r\n    if (prevValue === value) return $.Deferred().resolve()\r\n    else $el.data('bs.validator.previous', value)\r\n\r\n    if ($el.is('[type=\"radio\"]')) $el = this.$element.find('input[name=\"' + $el.attr('name') + '\"]')\r\n\r\n    var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})\r\n    this.$element.trigger(e)\r\n    if (e.isDefaultPrevented()) return\r\n\r\n    var self = this\r\n\r\n    return this.runValidators($el).done(function (errors) {\r\n      $el.data('bs.validator.errors', errors)\r\n\r\n      errors.length\r\n        ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)\r\n        : self.clearErrors($el)\r\n\r\n      if (!prevErrors || errors.toString() !== prevErrors.toString()) {\r\n        e = errors.length\r\n          ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})\r\n          : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})\r\n\r\n        self.$element.trigger(e)\r\n      }\r\n\r\n      self.toggleSubmit()\r\n\r\n      self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))\r\n    })\r\n  }\r\n\r\n\r\n  Validator.prototype.runValidators = function ($el) {\r\n    var errors   = []\r\n    var deferred = $.Deferred()\r\n    var options  = this.options\r\n\r\n    $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()\r\n    $el.data('bs.validator.deferred', deferred)\r\n\r\n    function getErrorMessage(key) {\r\n      return $el.data(key + '-error')\r\n        || $el.data('error')\r\n        || key == 'native' && $el[0].validationMessage\r\n        || options.errors[key]\r\n    }\r\n\r\n    $.each(Validator.VALIDATORS, $.proxy(function (key, validator) {\r\n      if ((getValue($el) || $el.attr('required')) &&\r\n          ($el.data(key) || key == 'native') &&\r\n          !validator.call(this, $el)) {\r\n        var error = getErrorMessage(key)\r\n        !~errors.indexOf(error) && errors.push(error)\r\n      }\r\n    }, this))\r\n\r\n    if (!errors.length && getValue($el) && $el.data('remote')) {\r\n      this.defer($el, function () {\r\n        var data = {}\r\n        data[$el.attr('name')] = getValue($el)\r\n        $.get($el.data('remote'), data)\r\n          .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })\r\n          .always(function () { deferred.resolve(errors)})\r\n      })\r\n    } else deferred.resolve(errors)\r\n\r\n    return deferred.promise()\r\n  }\r\n\r\n  Validator.prototype.validate = function () {\r\n    var self = this\r\n\r\n    $.when(this.$inputs.map(function (el) {\r\n      return self.validateInput($(this), false)\r\n    })).then(function () {\r\n      self.toggleSubmit()\r\n      self.focusError()\r\n    })\r\n\r\n    return this\r\n  }\r\n\r\n  Validator.prototype.focusError = function () {\r\n    if (!this.options.focus) return\r\n\r\n    var $input = $(\".has-error:first :input\")\r\n    if ($input.length === 0) return\r\n\r\n    $(document.body).animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)\r\n    $input.focus()\r\n  }\r\n\r\n  Validator.prototype.showErrors = function ($el) {\r\n    var method = this.options.html ? 'html' : 'text'\r\n    var errors = $el.data('bs.validator.errors')\r\n    var $group = $el.closest('.form-group')\r\n    var $block = $group.find('.help-block.with-errors')\r\n    var $feedback = $group.find('.form-control-feedback')\r\n\r\n    if (!errors.length) return\r\n\r\n    errors = $('<ul/>')\r\n      .addClass('list-unstyled')\r\n      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))\r\n\r\n    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())\r\n    $block.empty().append(errors)\r\n    $group.addClass('has-error has-danger')\r\n\r\n    $group.hasClass('has-feedback')\r\n      && $feedback.removeClass(this.options.feedback.success)\r\n      && $feedback.addClass(this.options.feedback.error)\r\n      && $group.removeClass('has-success')\r\n  }\r\n\r\n  Validator.prototype.clearErrors = function ($el) {\r\n    var $group = $el.closest('.form-group')\r\n    var $block = $group.find('.help-block.with-errors')\r\n    var $feedback = $group.find('.form-control-feedback')\r\n\r\n    $block.html($block.data('bs.validator.originalContent'))\r\n    $group.removeClass('has-error has-danger')\r\n\r\n    $group.hasClass('has-feedback')\r\n      && $feedback.removeClass(this.options.feedback.error)\r\n      && getValue($el)\r\n      && $feedback.addClass(this.options.feedback.success)\r\n      && $group.addClass('has-success')\r\n  }\r\n\r\n  Validator.prototype.hasErrors = function () {\r\n    function fieldErrors() {\r\n      return !!($(this).data('bs.validator.errors') || []).length\r\n    }\r\n\r\n    return !!this.$inputs.filter(fieldErrors).length\r\n  }\r\n\r\n  Validator.prototype.isIncomplete = function () {\r\n    function fieldIncomplete() {\r\n      return !getValue($(this))\r\n    }\r\n\r\n    return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length\r\n  }\r\n\r\n  Validator.prototype.onSubmit = function (e) {\r\n    this.validate()\r\n    if (this.isIncomplete() || this.hasErrors()) e.preventDefault()\r\n  }\r\n\r\n  Validator.prototype.toggleSubmit = function () {\r\n    if (!this.options.disable) return\r\n    this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())\r\n  }\r\n\r\n  Validator.prototype.defer = function ($el, callback) {\r\n    callback = $.proxy(callback, this, $el)\r\n    if (!this.options.delay) return callback()\r\n    window.clearTimeout($el.data('bs.validator.timeout'))\r\n    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))\r\n  }\r\n\r\n  Validator.prototype.destroy = function () {\r\n    this.$element\r\n      .removeAttr('novalidate')\r\n      .removeData('bs.validator')\r\n      .off('.bs.validator')\r\n      .find('.form-control-feedback')\r\n        .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))\r\n\r\n    this.$inputs\r\n      .off('.bs.validator')\r\n      .removeData(['bs.validator.errors', 'bs.validator.deferred', 'bs.validator.previous'])\r\n      .each(function () {\r\n        var $this = $(this)\r\n        var timeout = $this.data('bs.validator.timeout')\r\n        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')\r\n      })\r\n\r\n    this.$element.find('.help-block.with-errors').each(function () {\r\n      var $this = $(this)\r\n      var originalContent = $this.data('bs.validator.originalContent')\r\n\r\n      $this\r\n        .removeData('bs.validator.originalContent')\r\n        .html(originalContent)\r\n    })\r\n\r\n    this.$element.find('input[type=\"submit\"], button[type=\"submit\"]').removeClass('disabled')\r\n\r\n    this.$element.find('.has-error, .has-danger').removeClass('has-error has-danger')\r\n\r\n    return this\r\n  }\r\n\r\n  // VALIDATOR PLUGIN DEFINITION\r\n  // ===========================\r\n\r\n\r\n  function Plugin(option) {\r\n    return this.each(function () {\r\n      var $this   = $(this)\r\n      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)\r\n      var data    = $this.data('bs.validator')\r\n\r\n      if (!data && option == 'destroy') return\r\n      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))\r\n      if (typeof option == 'string') data[option]()\r\n    })\r\n  }\r\n\r\n  var old = $.fn.validator\r\n\r\n  $.fn.validator             = Plugin\r\n  $.fn.validator.Constructor = Validator\r\n\r\n\r\n  // VALIDATOR NO CONFLICT\r\n  // =====================\r\n\r\n  $.fn.validator.noConflict = function () {\r\n    $.fn.validator = old\r\n    return this\r\n  }\r\n\r\n\r\n  // VALIDATOR DATA-API\r\n  // ==================\r\n\r\n  $(window).on('load', function () {\r\n    $('form[data-toggle=\"validator\"]').each(function () {\r\n      var $form = $(this)\r\n      Plugin.call($form, $form.data())\r\n    })\r\n  })\r\n\r\n}(jQuery);\r\n"
  },
  {
    "path": "docs/conversion.md",
    "content": "---\nlayout: default\ntitle: Conversion\npermalink: /conversion/\nredirect_from: \n  - /docs/conversion.md/\n  - /docs/conversion/\n---\n\n# Conversion Matrix\n\n* TOC\n{:toc}\n\nThis document outlines all possible conversion details regarding `compose.yaml` values to Kubernetes / OpenShift artifacts.\n\n## Version Support\n\nUnder the hood, we're using [compose-go](https://github.com/compose-spec/compose-go), the reference library for parsing Compose files. We should be able to load all versions of Compose files.\nWe're doing our best to keep it up to date as soon as possible in our releases to be compatible with the latest features defined in the [Compose specification](https://github.com/compose-spec/compose-spec/blob/master/spec.md). If you absolutely need a feature we don't support yet, please open a PR!\n\n## Conversion Table\n\n**Glossary:**\n\n- **✓:** Converts\n- **-:** Not in this Compose Version\n- **n:** Not yet implemented\n- **x:** Not applicable / no 1-1 conversion\n\n| Keys                   | V1 | V2 | V3 | Kubernetes / OpenShift                                               | Notes                                                                                                                             |\n| ---------------------- | -- | -- | -- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| build                  | ✓  | ✓  | ✓  |                                                                      | Builds/Pushes to Docker repository. See [user guide on build and push image](https://kompose.io/user-guide/#build-and-push-image) |\n| build: context         | ✓  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n| build: dockerfile      | ✓  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n| build: args            | n  | n  | n  |                                                                      |                                                                                                                                   |\n| build: cache_from      | -  | -  | n  |                                                                      |                                                                                                                                   |\n| cap_add                | ✓  | ✓  | ✓  | Container.SecurityContext.Capabilities.Add                           |                                                                                                                                   |\n| cap_drop               | ✓  | ✓  | ✓  | Container.SecurityContext.Capabilities.Drop                          |                                                                                                                                   |\n| command                | ✓  | ✓  | ✓  | Container.Args                                                       |                                                                                                                                   |\n| configs                | n  | n  | ✓  |                                                                      |                                                                                                                                    |\n| configs: short-syntax  | n  | n  | ✓  |                                                                      | Only create configMap                                                                                                             |\n| configs: long-syntax   | n  | n  | ✓  |                                                                      | If target path is /, ignore this and only create configMap                                                                        |\n| cgroup_parent          | x  | x  | x  |                                                                      | Not supported within Kubernetes. See issue https://github.com/kubernetes/kubernetes/issues/11986                                  |\n| container_name         | ✓  | ✓  | ✓  | Metadata.Name + Deployment.Spec.Containers.Name                      |                                                                                                                                   |\n| credential_spec        | x  | x  | x  |                                                                      | Only applicable to Windows containers                                                                                             |\n| deploy                 | -  | -  | ✓  |                                                                      |                                                                                                                                   |\n| deploy: mode           | -  | -  | ✓  |                                                                      |                                                                                                                                   |\n| deploy: replicas       | -  | -  | ✓  | Deployment.Spec.Replicas / DeploymentConfig.Spec.Replicas            |                                                                                                                                   |\n| deploy: placement      | -  | -  | ✓  | Affinity                                                             |                                                                                                                                   |\n| deploy: update_config  | -  | -  | ✓  | Workload.Spec.Strategy                                               | Deployment / DeploymentConfig                                                                                                     |\n| deploy: resources      | -  | -  | ✓  | Containers.Resources.Limits.Memory / Containers.Resources.Limits.CPU | Support for memory as well as cpu                                                                                                 |\n| deploy: restart_policy | -  | -  | ✓  | Pod generation                                                       | This generated a Pod, see the [user guide on restart](http://kompose.io/user-guide/#restart)                                      |\n| deploy: labels         | -  | -  | ✓  | Workload.Metadata.Labels                                             | Only applied to workload resource                                                                                                 |\n| devices                | x  | x  | x  |                                                                      | Not supported within Kubernetes, See issue https://github.com/kubernetes/kubernetes/issues/5607                                   |\n| depends_on             | x  | x  | x  |                                                                      |                                                                                                                                   |\n| dns                    | x  | x  | x  |                                                                      | Not used within Kubernetes. Kubernetes uses a managed DNS server                                                                  |\n| dns_search             | x  | x  | x  |                                                                      | See `dns` key                                                                                                                     |\n| domainname             | ✓  | ✓  | ✓  | SubDomain                                                            |                                                                                                                                   |\n| tmpfs                  | ✓  | ✓  | ✓  | Containers.Volumes.EmptyDir                                          | Creates emptyDirvolume with medium set to Memory & mounts given directory inside container                                        |\n| entrypoint             | ✓  | ✓  | ✓  | Container.Command                                                    |                                                                                                                                   |\n| env_file               | n  | n  | ✓  |                                                                      |                                                                                                                                   |\n| environment            | ✓  | ✓  | ✓  | Container.Env                                                        |                                                                                                                                   |\n| expose                 | ✓  | ✓  | ✓  | Service.Spec.Ports                                                   |                                                                                                                                   |\n| endpoint_mode          | n  | n  | ✓  |                                                                      | If endpoint_mode=vip, the created Service will be forced to set to NodePort type                                                  |\n| extends                | ✓  | ✓  | ✓  |                                                                      | Extends by utilizing the same image supplied                                                                                      |\n| external_links         | x  | x  | x  |                                                                      | Kubernetes uses a flat-structure for all containers and thus external_links does not have a 1-1 conversion                        |\n| extra_hosts            | n  | n  | n  |                                                                      |                                                                                                                                   |\n| group_add              | ✓  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n| healthcheck            | -  | n  | ✓  |                                                                      |                                                                                                                                   |\n| hostname               | ✓  | ✓  | ✓  | HostName                                                             |                                                                                                                                   |\n| image                  | ✓  | ✓  | ✓  | Deployment.Spec.Containers.Image                                     |                                                                                                                                   |\n| isolation              | x  | x  | x  |                                                                      | Not applicable as this applies to Windows with HyperV support                                                                     |\n| labels                 | ✓  | ✓  | ✓  | Metadata.Annotations                                                 |                                                                                                                                   |\n| links                  | x  | x  | x  |                                                                      | All containers in the same pod are accessible in Kubernetes                                                                       |\n| logging                | x  | x  | x  |                                                                      | Kubernetes has built-in logging support at the node-level                                                                         |\n| network_mode           | x  | x  | x  |                                                                      | Kubernetes uses its own cluster networking                                                                                        |\n| networks               | ✓  | ✓  | ✓  |                                                                      | See `networks` key                                                                                                                |\n| networks: aliases      | x  | x  | x  |                                                                      | See `networks` key                                                                                                                |\n| networks: addresses    | x  | x  | x  |                                                                      | See `networks` key                                                                                                                |\n| pid                    | ✓  | ✓  | ✓  | HostPID                                                              |                                                                                                                                   |\n| ports                  | ✓  | ✓  | ✓  | Service.Spec.Ports                                                   |                                                                                                                                   |\n| ports: short-syntax    | ✓  | ✓  | ✓  | Service.Spec.Ports                                                   |                                                                                                                                   |\n| ports: long-syntax     | -  | -  | ✓  | Service.Spec.Ports                                                   |                                                                                                                                   |\n| secrets                | -  | -  | ✓  | Secret                                                               | External Secret is not Supported                                                                                                  |\n| secrets: short-syntax  | -  | -  | ✓  | Secret                                                               | External Secret is not Supported                                                                                                  |\n| secrets: long-syntax   | -  | -  | ✓  | Secret                                                               | External Secret is not Supported                                                                                                  |\n| security_opt           | x  | x  | x  |                                                                      | Kubernetes uses its own container naming scheme                                                                                   |\n| stop_grace_period      | ✓  | ✓  | ✓  | TerminationGracePeriodSeconds                                        |                                                                                                                                   |\n| stop_signal            | x  | x  | x  |                                                                      | Not supported within Kubernetes. See issue https://github.com/kubernetes/kubernetes/issues/30051                                  |\n| sysctls                | n  | n  | n  |                                                                      |                                                                                                                                   |\n| ulimits                | x  | x  | x  |                                                                      | Not supported within Kubernetes. See issue https://github.com/kubernetes/kubernetes/issues/3595                                   |\n| userns_mode            | x  | x  | x  |                                                                      | Not supported within Kubernetes and ignored in Compose Version 3                                                           |\n| volumes                | ✓  | ✓  | ✓  | PersistentVolumeClaim                                                | Creates a PersistentVolumeClaim. Can only be created if there is already a PersistentVolume within the cluster                    |\n| volumes: short-syntax  | ✓  | ✓  | ✓  | PersistentVolumeClaim                                                | Creates a PersistentVolumeClaim. Can only be created if there is already a PersistentVolume within the cluster                    |\n| volumes: long-syntax   | -  | -  | ✓  | PersistentVolumeClaim                                                | Creates a PersistentVolumeClaim. Can only be created if there is already a PersistentVolume within the cluster                    |\n| restart                | ✓  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n|                        |    |    |    |                                                                      |                                                                                                                                   |\n| **Volume**             | x  | x  | x  |                                                                      |                                                                                                                                   |\n| driver                 | x  | x  | x  |                                                                      |                                                                                                                                   |\n| driver_opts            | x  | x  | x  |                                                                      |                                                                                                                                   |\n| external               | x  | x  | x  |                                                                      |                                                                                                                                   |\n| labels                 | x  | x  | x  |                                                                      |                                                                                                                                   |\n|                        |    |    |    |                                                                      |                                                                                                                                   |\n| **Network**            | x  | x  | x  |                                                                      |                                                                                                                                   |\n| driver                 | x  | x  | x  |                                                                      |                                                                                                                                   |\n| driver_opts            | x  | x  | x  |                                                                      |                                                                                                                                   |\n| enable_ipv6            | x  | x  | x  |                                                                      |                                                                                                                                   |\n| ipam                   | x  | x  | x  |                                                                      |                                                                                                                                   |\n| internal               | x  | x  | x  |                                                                      |                                                                                                                                   |\n| labels                 | x  | x  | x  |                                                                      |                                                                                                                                   |\n| external               | x  | x  | x  |                                                                      |                                                                                                                                   |\n|                        |    |    |    |                                                                      |                                                                                                                                   |\n| **Configs**            | x  | x  | x  |                                                                      |                                                                                                                                   |\n| environment            | x  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n| file                   | ✓  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n| content                | x  | ✓  | ✓  |                                                                      |                                                                                                                                   |\n| labels                 | x  | x  | x  |                                                                      |                                                                                                                                   |\n| external               | x  | x  | x  |                                                                      |                                                                                                                                   |\n"
  },
  {
    "path": "docs/development.md",
    "content": "---\nlayout: default\npermalink: /development/\ntitle: Development\nredirect_from: \n  - /docs/development.md/\n  - /docs/development/\n---\n\n# Development Guide\n\n## Building Kompose\n\nRead about building kompose [here](https://github.com/kubernetes/kompose#development-and-building-of-kompose).\n\n## Workflow\n\n### Fork the main repository\n\n1. Go to https://github.com/kubernetes/kompose\n2. Click the \"Fork\" button (at the top right)\n\n### Clone your fork\n\nThe commands below require that you have `$GOPATH`. We highly recommended you put the Kompose code into your `$GOPATH`.\n\n```console\ngit clone https://github.com/$YOUR_GITHUB_USERNAME/kompose.git $GOPATH/src/github.com/kubernetes/kompose\ncd $GOPATH/src/github.com/kubernetes/kompose\ngit remote add upstream 'https://github.com/kubernetes/kompose'\n```\n\n### Create a branch and make changes\n\n```console\ngit checkout -b myfeature\n# Make your code changes\n```\n\n### Keeping your development fork in sync\n\n```console\ngit fetch upstream\ngit rebase upstream/main\n```\n\nNote: If you have write access to the main repository at github.com/kubernetes/kompose, you should modify your git configuration so that you can't accidentally push to upstream:\n\n```console\ngit remote set-url --push upstream no_push\n```\n\n### Committing changes to your fork\n\n```console\ngit commit\ngit push -f origin myfeature\n```\n\n### Creating a pull request\n\n1. Visit https://github.com/$YOUR_GITHUB_USERNAME/kompose.git\n2. Click the \"Compare and pull request\" button next to your \"myfeature\" branch.\n3. Check out the pull request process for more details\n\n## Go Modules and dependency management\n\nKompose uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.\nIf you want to introduce changes to dependencies, please ensure that `go.mod` and `go.sum` are updated properly.\n\n##### Updating Kubernetes and OpenShift\n\nKubernetes version depends on what version is OpenShift using.\nOpenShift is using forked Kubernetes to carry some patches.\nCurrently, it is not possible to use a different Kubernetes version from the version that OpenShift uses.\n(for more see comments in `go.mod`)\n\n### Adding CLI tests\n\n[Kompose CLI tests](https://github.com/kubernetes/kompose/tree/main/script/test/cmd) run `kompose convert` with compose files, and cross-check the k8s and OpenShift artifacts generated with the template files.\n\n\n\n### CI\n\nFor Kompose, we use numerous CI's:\n\n- [TravisCI](https://travis-ci.org/kubernetes/kompose): Unit and CLI tests\n- [SemaphoreCI](https://semaphoreci.com/cdrage/kompose-2): Integration / cluster tests\n- [Fabric8CI](http://jenkins.cd.k8s.fabric8.io/): Secondary integration tests / future cluster tests\n"
  },
  {
    "path": "docs/feed.xml",
    "content": "---\nlayout: null\n---\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n  <channel>\n    <title>{{ site.title | xml_escape }}</title>\n    <description>{{ site.description | xml_escape }}</description>\n    <link>{{ site.url }}{{ site.baseurl }}/</link>\n    <atom:link href=\"{{ \"/feed.xml\" | prepend: site.baseurl | prepend: site.url }}\" rel=\"self\" type=\"application/rss+xml\"/>\n    <pubDate>{{ site.time | date_to_rfc822 }}</pubDate>\n    <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>\n    <generator>Jekyll v{{ jekyll.version }}</generator>\n    {% for doc in site.docs limit:10 %}\n      <item>\n        <title>{{ doc.title | xml_escape }}</title>\n        <description>{{ doc.content | xml_escape }}</description>\n        <pubDate>{{ doc.date | date_to_rfc822 }}</pubDate>\n        <link>{{ doc.url | prepend: site.baseurl | prepend: site.url }}</link>\n        <guid isPermaLink=\"true\">{{ doc.url | prepend: site.baseurl | prepend: site.url }}</guid>\n      </item>\n    {% endfor %}\n  </channel>\n</rss>\n"
  },
  {
    "path": "docs/getting-started.md",
    "content": "---\nlayout: default\npermalink: /getting-started/\ntitle: Getting Started\nredirect_from:\n  - /docs/getting-started.md/\n  - /docs/getting-started/\n---\n\n# Getting Started\n\n* TOC\n{:toc}\n\nThis is how you'll get started with Kompose!\n\nThere are three different guides depending on your container orchestrator as well as operating system.\n\nFor beginners and the most compatibility, follow the _Minikube and Kompose_ guide.\n\n## Minikube and Kompose\n\nIn this guide, we'll deploy a sample `compose.yaml` file to a Kubernetes cluster.\n\nRequirements:\n\n- [minikube](https://github.com/kubernetes/minikube)\n- [kompose](https://github.com/kubernetes/kompose)\n\n**Start `minikube`:**\n\nIf you don't already have a Kubernetes cluster running, [minikube](https://github.com/kubernetes/minikube) is the best way to get started.\n\n```sh\n$ minikube start\nStarting local Kubernetes v1.7.5 cluster...\nStarting VM...\nGetting VM IP address...\nMoving files into cluster...\nSetting up certs...\nConnecting to cluster...\nSetting up kubeconfig...\nStarting cluster components...\nKubectl is now configured to use the cluster\n```\n\n**Download an [example Compose file](https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml), or use your own:**\n\n```sh\nwget https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml\n```\n\n**Convert your Compose file to Kubernetes:**\n\nRun `kompose convert` in the same directory as your `compose.yaml` file.\n\n```sh\n$ kompose convert\nINFO Kubernetes file \"frontend-service.yaml\" created\nINFO Kubernetes file \"redis-leader-service.yaml\" created\nINFO Kubernetes file \"redis-replica-service.yaml\" created\nINFO Kubernetes file \"frontend-deployment.yaml\" created\nINFO Kubernetes file \"redis-leader-deployment.yaml\" created\nINFO Kubernetes file \"redis-replica-deployment.yaml\" created\n```\n\nThen you can use `kubectl apply` to create these resources in Kubernetes.\n\n**Access the newly deployed service:**\n\nNow that your service has been deployed, let's access it.\n\nIf you're using `minikube` you may access it via the `minikube service` command.\n\n```sh\n$ minikube service frontend\n```\n\nOtherwise, use `kubectl` to see what IP the service is using:\n\n```sh\n$ kubectl describe svc frontend\nName:                   frontend\nNamespace:              default\nLabels:                 service=frontend\nSelector:               service=frontend\nType:                   LoadBalancer\nIP:                     10.0.0.183\nLoadBalancer Ingress:   123.45.67.89\nPort:                   80      80/TCP\nNodePort:               80      31144/TCP\nEndpoints:              172.17.0.4:80\nSession Affinity:       None\nNo events.\n```\n\nNote: If you're using a cloud provider, your IP will be listed next to `LoadBalancer Ingress`.\n\nIf you have yet to expose your service (for example, within GCE), use the command:\n\n```sh\nkubectl expose deployment frontend --type=\"LoadBalancer\"\n```\n\nTo check functionality, you may also `curl` the URL.\n\n```sh\n$ curl http://123.45.67.89\n```\n\n## Minishift and Kompose\n\nIn this guide, we'll deploy a sample `compose.yaml` file to an OpenShift cluster.\n\nRequirements:\n\n- [minishift](https://github.com/minishift/minishift)\n- [kompose](https://github.com/kubernetes/kompose)\n- An OpenShift route created\n\n**Note:** The service will NOT be accessible until you create an OpenShift route with `oc expose`. You must also have a virtualization environment setup. By default, `minishift` uses KVM.\n\n**Start `minishift`:**\n\n[Minishift](https://github.com/minishift/minishift) is a tool that helps run OpenShift locally using a single-node cluster inside a VM. Similar to [minikube](https://github.com/kubernetes/minikube).\n\n```sh\n$ minishift start\nStarting local OpenShift cluster using 'kvm' hypervisor...\n-- Checking OpenShift client ... OK\n-- Checking Docker client ... OK\n-- Checking Docker version ... OK\n-- Checking for existing OpenShift container ... OK\n...\n```\n\n**Download an [example Compose file](https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml), or use your own:**\n\n```sh\nwget https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml\n```\n\n**Convert your Compose file to OpenShift:**\n\nRun `kompose convert --provider=openshift` in the same directory as your `compose.yaml` file.\n\n```sh\n$ kompose convert --provider=openshift\nINFO OpenShift file \"frontend-service.yaml\" created\nINFO OpenShift file \"redis-leader-service.yaml\" created\nINFO OpenShift file \"redis-replica-service.yaml\" created\nINFO OpenShift file \"frontend-deploymentconfig.yaml\" created\nINFO OpenShift file \"frontend-imagestream.yaml\" created\nINFO OpenShift file \"redis-leader-deploymentconfig.yaml\" created\nINFO OpenShift file \"redis-leader-imagestream.yaml\" created\nINFO OpenShift file \"redis-replica-deploymentconfig.yaml\" created\nINFO OpenShift file \"redis-replica-imagestream.yaml\" created\n```\n\nThen you can use `kubectl apply` to create these resources in OpenShift cluster.\n\n**Access the newly deployed service:**\n\nAfter deployment, you must create an OpenShift route in order to access the service.\n\nIf you're using `minishift`, you'll use a combination of `oc` and `minishift` commands to access the service.\n\nCreate a route for the `frontend` service using `oc`:\n\n```sh\n$ oc expose service/frontend\nroute \"frontend\" exposed\n```\n\nAccess the `frontend` service with `minishift`:\n\n```sh\n$ minishift openshift service frontend --namespace=myproject\nOpening the service myproject/frontend in the default browser...\n```\n\nYou can also access the GUI interface of OpenShift for an overview of the deployed containers:\n\n```sh\n$ minishift console\nOpening the OpenShift Web console in the default browser...\n```\n\n## RHEL and Kompose\n\nIn this guide, we'll deploy a sample `compose.yaml` file using both RHEL (Red Hat Enterprise Linux) and OpenShift.\n\nRequirements:\n\n- Red Hat Enterprise Linux 7.4\n- [Red Hat Development Suite](https://developers.redhat.com/products/devsuite/overview/)\n  - Which includes:\n  - [minishift](https://github.com/minishift/minishift)\n  - [kompose](https://github.com/kubernetes/kompose)\n\n**Note:** A KVM hypervisor must be setup in order to correctly use `minishift` on RHEL. You can set it up via the [CDK Documentation](https://access.redhat.com/documentation/en-us/red_hat_container_development_kit/3.1/html-single/getting_started_guide/index#setup-virtualization) under \"Set up your virtualization environment\".\n\n**Install Red Hat Development Suite:**\n\nBefore we are able to use both `minishift` and `kompose`, DevSuite must be installed. A more concise [installation document is available](https://developers.redhat.com/products/cdk/hello-world#fndtn-rhel).\n\nChange to root.\n\n```sh\n$ su -\n```\n\nEnable the Red Hat Developer Tools software repository.\n\n```sh\n$ subscription-manager repos --enable rhel-7-server-devtools-rpms\n$ subscription-manager repos --enable rhel-server-rhscl-7-rpms\n```\n\nAdd the Red Hat Developer Tools key to your system.\n\n```sh\n$ cd /etc/pki/rpm-gpg\n$ wget -O RPM-GPG-KEY-redhat-devel https://www.redhat.com/security/data/a5787476.txt\n$ rpm --import RPM-GPG-KEY-redhat-devel\n```\n\nInstall Red Hat Development Suite and Kompose.\n\n```sh\n$ yum install rh-devsuite kompose -y\n```\n\n**Start `minishift`:**\n\nBefore we begin, we must do a few preliminary steps setting up `minishift`.\n\n```sh\n$ su -\n$ ln -s /var/lib/cdk-minishift-3.0.0/minishift /usr/bin/minishift\n$ minishift setup-cdk --force --default-vm-driver=\"kvm\"\n$ ln -s /home/$(whoami)/.minishift/cache/oc/v3.5.5.8/oc /usr/bin/oc\n```\n\nNow we may start `minishift`.\n\n```sh\n$ minishift start\nStarting local OpenShift cluster using 'kvm' hypervisor...\n-- Checking OpenShift client ... OK\n-- Checking Docker client ... OK\n-- Checking Docker version ... OK\n-- Checking for existing OpenShift container ... OK\n...\n```\n\n**Download an [example Compose file](https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml), or use your own:**\n\n```sh\nwget https://raw.githubusercontent.com/kubernetes/kompose/main/examples/compose.yaml\n```\n\n**Convert your Compose file to OpenShift:**\n\nRun `kompose convert --provider=openshift` in the same directory as your `compose.yaml` file.\n\n```sh\n$ kompose convert --provider=openshift\nINFO OpenShift file \"frontend-service.yaml\" created\nINFO OpenShift file \"redis-leader-service.yaml\" created\nINFO OpenShift file \"redis-replica-service.yaml\" created\nINFO OpenShift file \"frontend-deploymentconfig.yaml\" created\nINFO OpenShift file \"frontend-imagestream.yaml\" created\nINFO OpenShift file \"redis-leader-deploymentconfig.yaml\" created\nINFO OpenShift file \"redis-leader-imagestream.yaml\" created\nINFO OpenShift file \"redis-replica-deploymentconfig.yaml\" created\nINFO OpenShift file \"redis-replica-imagestream.yaml\" created\n```\n\nThen you can use `kubectl apply` to create these resources in OpenShift.\n\n**Access the newly deployed service:**\n\nAfter deployment, you must create an OpenShift route in order to access the service.\n\nIf you're using `minishift`, you'll use a combination of `oc` and `minishift` commands to access the service.\n\nCreate a route for the `frontend` service using `oc`:\n\n```sh\n$ oc expose service/frontend\nroute \"frontend\" exposed\n```\n\nAccess the `frontend` service with `minishift`:\n\n```sh\n$ minishift openshift service frontend --namespace=myproject\nOpening the service myproject/frontend in the default browser...\n```\n\nYou can also access the GUI interface of OpenShift for an overview of the deployed containers:\n\n```sh\n$ minishift console\nOpening the OpenShift Web console in the default browser...\n```\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\n# Feel free to add content and custom Front Matter to this file.\n# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults\n\nlayout: index\n---\n\n```sh\n$ kompose convert -f compose.yaml\n\n$ kubectl apply -f .\n\n$ kubectl get po\nNAME                            READY     STATUS              RESTARTS   AGE\nfrontend-591253677-5t038        1/1       Running             0          10s\nredis-leader-2410703502-9hshf   1/1       Running             0          10s\nredis-replica-4049176185-hr1lr  1/1       Running             0          10s\n```\n"
  },
  {
    "path": "docs/installation.md",
    "content": "---\nlayout: default\npermalink: /installation/\ntitle: Installation\nredirect_from:\n  - /docs/installation.md/\n  - /docs/installation/\n---\n\n# Installation\n\n* TOC\n{:toc}\n\nWe have multiple ways to install Kompose. Our preferred (and most up-to-date) method is downloading the binary from the latest GitHub release.\n\n## GitHub release\n\nKompose is released via GitHub, you can see all current releases on the [GitHub release page](https://github.com/kubernetes/kompose/releases).\n\nThis is the **recommended** way of installing Kompose.\n\n**Linux and macOS:**\n\n```sh\n# Linux\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-linux-amd64 -o kompose\n\n# Linux ARM64\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-linux-arm64 -o kompose\n\n# macOS\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-darwin-amd64 -o kompose\n\n# macOS ARM64\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-darwin-arm64 -o kompose\n\nchmod +x kompose\nsudo mv ./kompose /usr/local/bin/kompose\n```\n\n**Windows:**\n\nDownload from [GitHub](https://github.com/kubernetes/kompose/releases/download/v1.38.0/kompose-windows-amd64.exe) and add the binary to your PATH.\n\n## Go\n\nInstalling using `go install` pulls from the main branch with the latest development changes.\n\n```sh\ngo install github.com/kubernetes/kompose@latest\n```\n\n## CentOS\n\nKompose is in [EPEL](https://fedoraproject.org/wiki/EPEL) (Available in EPEL 7 package repository) CentOS repository.\nIf you don't have [EPEL](https://fedoraproject.org/wiki/EPEL) repository already installed and enabled you can do it by running `sudo yum install epel-release`\n\nIf you have [EPEL](https://fedoraproject.org/wiki/EPEL) enabled in your system, you can install Kompose like any other package.\n\n```bash\nsudo yum -y install kompose\n```\n\n## macOS\n\nOn macOS, you can install the latest release via [Homebrew](https://brew.sh) or [MacPorts](https://www.macports.org/).\n\n```bash\nbrew install kompose\n```\n\n## Windows\n\nKompose can be installed via [Chocolatey](https://chocolatey.org/packages/kubernetes-kompose)\n\n```console\nchoco install kubernetes-kompose\n```\n\nor using winget\n\n```console\nwinget install Kubernetes.kompose\n```\n\n## Docker\n\nYou can build an image from the official repo for [Docker](https://docs.docker.com/engine/reference/commandline/build/) or [Podman](https://docs.podman.io/en/latest/markdown/podman-build.1.html):\n\n```bash\ndocker build -t kompose https://github.com/kubernetes/kompose.git\\#main\n```\n\nTo run the built image against the current directory, run the following command:\n\n```bash\ndocker run --rm -it -v $PWD:/opt -w /opt kompose kompose convert\n```\n"
  },
  {
    "path": "docs/integrations.md",
    "content": "---\nlayout: default\npermalink: /integrations/\ntitle: Integrations\nredirect_from:\n  - /docs/integrations.md/\n  - /docs/integrations/\n---\n\n# Integrations\n\n* TOC\n{:toc}\n\nThere are some projects out there known to use Kompose integrated in some form or another\n\n### Kompose UI by Jad Chamoun (ICANN) and Joe Haddad (Anghami)\n\n**Description:** \"A web interface to convert Compose files to Kubernetes YAML\"\n\n**Link:** [https://github.com/JadCham/komposeui](https://github.com/JadCham/komposeui)\n\n### Kompose Docker Container by Cloudfind\n\n**Description:** \"A Docker container for the Kompose translator for compose\"\n\n**Link:** [https://github.com/cloudfind/kompose-docker](https://github.com/cloudfind/kompose-docker)\n\n### KPM by CoreOS\n\n**Description:** \"KPM is a tool to deploy and manage application stacks on Kubernetes\"\n\n**Link:** [https://github.com/coreos/kpm](https://github.com/coreos/kpm)\n\n### Docker Image for Adobe Enterprise Manager by Adfinis SyGroup AG\n\n**Description:** \"Docker Image for Adobe Enterprise Manager\"\n\n**Link:** [https://github.com/adfinis-sygroup/aem-docker/tree/master](https://github.com/adfinis-sygroup/aem-docker/tree/master)\n\n### Kompose Ansible Playbook by Chris Houseknecht (Red Hat)\n\n**Description:** \"Download and unarchive the latest kompose release asset for your OS\"\n\n**Link:** [https://github.com/chouseknecht/kompose-install-role](https://github.com/chouseknecht/kompose-install-role)\n\n### Fabric8 Maven Plugin by Red Hat\n\n**Description:** \"Maven is one of the widely used build tools for Java applications. The Fabric8 Maven Plugin is a maven extension that simplifies the deployment of Java applications to Kubernetes or OpenShift clusters.\nThe main task of this plugin is to build Docker images, generate Kubernetes or OpenShift resource descriptors and run/deploy the application on Kubernetes or OpenShift cluster.\nThe plugin has a wide range of configuration options. Compose is one of the options to bring up deployments on Kubernetes or OpenShift clusters.\nTechnically, Fabric8 Maven Plugin processes the external compose.yml file and generates Kubernetes or OpenShift resources via Kompose.\"\n\n**Links:**\n\n* [Quickstart](/maven-example)\n* [Documentation](https://maven.fabric8.io/#compose)\n"
  },
  {
    "path": "docs/maven-example.md",
    "content": "---\nlayout: default\npermalink: /maven-example/\ntitle: Maven Example\nredirect_from:\n  - /docs/maven-example.md/\n  - /docs/maven-example/\n---\n\n# Fabric8 Maven Plugin + Kompose:\n\nLet's deploy a Springboot Java application with Compose file using Fabric8 Maven Plugin to Kubernetes or OpenShift.\n\n##### Requirements\n\n- Linux or MacOS or Windows\n- JDK 1.7+ - [JDK Quick Installation Guide](http://openjdk.java.net/install/)\n- Maven 3.x+ - [Maven Installation Guide](http://www.baeldung.com/install-maven-on-windows-linux-mac)\n- Kompose - [Kompose Installation Guide](/installation)\n\n**1. Clone the example project from GitHub**\n\n```bash\n$ git clone https://github.com/piyush1594/kompose-maven-example.git\n```\n\nChange current directory to `kompose-maven-example` directory.\n\n```bash\n$ cd kompose-maven-example\n```\n\n**2. Add Fabric8 Maven Plugin to your project**\n\n```bash\n$ mvn io.fabric8:fabric8-maven-plugin:3.5.28:setup\n```\n\nAdd the Fabric8 Maven Plugin configuration to `pom.xml` of project. `pom.xml` is manifest or deployment descriptor file of a maven project.\n\n**3. Install Kompose through Maven**\n\n```bash\n$ mvn fabric8:install\n```\n\nThis command installs the `kompose` on the host.\n\n**4. Configure Fabric8 Maven Plugin to use a Compose file**\n\n```bash\n<plugin>\n  <groupId>io.fabric8</groupId>\n  <artifactId>fabric8-maven-plugin</artifactId>\n  <configuration>\n    <composeFile>path for docker compose file</composeFile>\n  </configuration>\n  <executions>\n    <execution>\n      <goals>\n        <goal>resource</goal>\n        <goal>build</goal>\n      </goals>\n    </execution>\n  </executions>\n</plugin>\n```\n\nAdd the `<configuration>` and `<executions>` sections to `pom.xml` as shown in above `pom.xml` snippet. Update the `<composeFile>` to provide the relative path of Compose file from `pom.xml`\n\n**5. Deploy application on Kubernetes or OpenShift**\n\nMake sure that Kubernetes/OpenShift cluster or Minikube/Minishift is running. In case, if anything of this is not running, you can run Minishift to test this application by using the following command.\n\n```bash\n$ minishift start\n```\n\nBelow command deploys this application on Kubernetes or OpenShift.\n\n```bash\n$ mvn fabric8:deploy\n```\n\nNow that your service has been deployed, let's access it by querying `pod`, `service` from Kubernetes or OpenShift.\n\n```bash\n$ oc get pods\nNAME                                    READY     STATUS      RESTARTS   AGE\nspringboot-compose-1-xl0vb       1/1       Running     0          5m\nspringboot-compose-s2i-1-build   0/1       Completed   0          7m\n```\n\n```bash\n$ oc get svc\nNAME                        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE\nspringboot-compose   172.30.205.137   <none>        8080/TCP   6m\n```\n\nLet's access the Springboot service.\n\n```bash\n$ minishift openshift service --in-browser springboot-compose\nCreated the new window in existing browser session.\n```\n\nIt will open your application endpoint in default browser.\n\n![Output-Diagram](https://github.com/kubernetes/kompose/blob/main/docs/images/kompose-maven-output-diagram.png)\n"
  },
  {
    "path": "docs/user-guide.md",
    "content": "---\nlayout: default\npermalink: /user-guide/\ntitle: User Guide\nredirect_from:\n  - /docs/user-guide.md/\n  - /docs/user-guide/\n---\n\n# User Guide\n\n## Table of contents\n\n* [Kompose conversion example](#kompose-conversion-example)\n* [CLI Modifications](#cli-modifications)\n* [Labels](#labels)\n* [Restart Policy](#restart-policy)\n* [Building and Pushing Images](#building-and-pushing-images)\n\n## Kompose Conversion Example\n\nKompose has support for two providers: OpenShift and Kubernetes.\nYou can choose a targeted provider using global option `--provider`. If no provider is specified, Kubernetes is set by default.\n\n### Kubernetes\n\n```sh\n$ kompose --file compose.yaml convert\n```\n\nYou can also provide multiple compose files at the same time:\n\n```sh\n$ kompose -f compose.yaml -f compose.yaml convert\n```\n\nWhen multiple compose files are provided the configuration is merged. Any configuration that is common will be over ridden by subsequent file.\n\nYou can provide your compose files via environment variables as following:\n```sh\n$ COMPOSE_FILE=\"compose.yaml alternative-compose.yaml\" kompose convert\n```\n\n### OpenShift\n\n```sh\n$ kompose --provider openshift --file compose.yaml convert\n```\n\n## CLI Modifications\n\nOn the command line, you can modify the output of the generated YAML. For example, using alternative controllers such as [Replication Controllers](http://kubernetes.io/docs/user-guide/replication-controller/) objects, [Daemon Sets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/), or [Statefulset](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/).\n\n\nDaemon Set example:\n\n```sh\n$ kompose convert --controller daemonSet\n```\n\nA full list of these options can be found on `kompose convert --help`.\n\n## Labels\n\n`kompose` supports Kompose-specific labels within the `compose.yaml` file to get you the rest of the way there.\n\nLabels are an important kompose concept as they allow you to add Kubernetes modifications without having to edit the YAML afterwards. For example, adding an init container, or a custom readiness check.\n\n| Key / Value | Description / Example |\n|-----|-------------|\n| [`kompose.controller.port.expose`](#komposecontrollerportexpose) | Expose as hostPort on the controller (not recommended) |\n| `Boolean` | `false` |\n| [`kompose.controller.type`](#komposecontrollertype) | Type of the controller |\n| `String` | `deployment`, `daemonset`, `replicationcontroller`, `statefulset` |\n| [`kompose.cronjob.backoff_limit`](#komposecronjobbackoff_limit) | Number of retries before marked as failed |\n| `Integer` | `6` |\n| [`kompose.cronjob.concurrency_policy`](#komposecronjobconcurrency_policy) | Handling of concurrent jobs |\n| `String` | `Forbid`, `Allow`, `Never` |\n| [`kompose.cronjob.schedule`](#komposecronjobschedule) | Schedule |\n| `String` | `1 * * * *` |\n| [`kompose.hpa.cpu`](#komposehpacpu) | CPU utilization percentage that triggers autoscaling |\n| `Percentage` | `50%` |\n| [`kompose.hpa.memory`](#komposehpamemory) | Memory utilization threshold that triggers autoscaling |\n| `String` | `200Mi` |\n| [`kompose.hpa.replicas.max`](#komposehpareplicasmax) | Max pod replicas for Horizontal Pod Autoscaler |\n| `Integer` | `10` |\n| [`kompose.hpa.replicas.min`](#komposehpareplicasmin) | Min pod replicas for Horizontal Pod Autoscaler |\n| `Integer` | `2` |\n| [`kompose.image-pull-policy`](#komposeimage-pull-policy) | Policy for pulling images |\n| `String` | `Always`, `IfNotPresent`, `Never` |\n| [`kompose.image-pull-secret`](#komposeimage-pull-secret) | Secret to be used for pulling images from a private registry |\n| `String` | `myregistrykey` |\n| [`kompose.init.containers.command`](#komposeinitcontainerscommand) | Command to be executed |\n| `Array` | `[\"printenv\"]` |\n| [`kompose.init.containers.image`](#komposeinitcontainersimage) | Image to be used |\n| `String` | `busybox` |\n| [`kompose.init.containers.name`](#komposeinitcontainersname) | Name assigned |\n| `String` | `init-mydb` |\n| [`kompose.security-context.fsgroup`](#komposesecurity-contextfsgroup) | Filesystem group ID for the pods' volumes |\n| `Integer` | `1001` |\n| [`kompose.service.external-traffic-policy`](#komposeserviceexternal-traffic-policy) | Policy to route external traffic |\n| `String` | `cluster`, `local` |\n| [`kompose.service.expose`](#komposeserviceexpose) | Creates a Ingress or Route. Accepts domain or 'true' for auto-generating a domain. |\n| `String` | `true,domain1.com,domain2.com` |\n| [`kompose.service.expose.ingress-class-name`](#komposeserviceexposeingress-class-name) | Ingress class to be used for exposing services |\n| `String` | `nginx` |\n| [`kompose.service.expose.tls-secret`](#komposeserviceexposetls-secret) | TLS secret for securing ingress |\n| `String` | `my-tls-secret` |\n| [`kompose.service.group`](#komposeservicegroup) | Label to group multiple containers in a single pod |\n| `String` | `mygroup` |\n| [`kompose.service.healthcheck.liveness.http_get_path`](#komposeservicehealthchecklivenesshttp_get_path) | HTTP GET path for liveness probe |\n| `String` | `/health` |\n| [`kompose.service.healthcheck.liveness.http_get_port`](#komposeservicehealthchecklivenesshttp_get_port) | HTTP GET port for liveness probe |\n| `Integer` | `8080` |\n| [`kompose.service.healthcheck.liveness.tcp_port`](#komposeservicehealthchecklivenesstcp_port) | TCP socket port for liveness probe |\n| `Integer` | `3306` |\n| [`kompose.service.healthcheck.readiness.disable`](#komposeservicehealthcheckreadinessdisable) | Whether to disable the readiness probe |\n| `Boolean` | `true` |\n| [`kompose.service.healthcheck.readiness.http_get_path`](#komposeservicehealthcheckreadinesshttp_get_path) | HTTP GET path for readiness probe |\n| `String` | `/ready` |\n| [`kompose.service.healthcheck.readiness.http_get_port`](#komposeservicehealthcheckreadinesshttp_get_port) | HTTP GET port for readiness probe |\n| `Integer` | `8081` |\n| [`kompose.service.healthcheck.readiness.interval`](#komposeservicehealthcheckreadinessinterval) | Interval between readiness checks |\n| `Duration` | `10s` |\n| [`kompose.service.healthcheck.readiness.retries`](#komposeservicehealthcheckreadinessretries) | Number of times readiness probe should retry before failing |\n| `Integer` | `3` |\n| [`kompose.service.healthcheck.readiness.start_period`](#komposeservicehealthcheckreadinessstart_period) | Initial delay before starting the readiness probe |\n| `Duration` | `30s` |\n| [`kompose.service.healthcheck.readiness.tcp_port`](#komposeservicehealthcheckreadinesstcp_port) | TCP socket port for readiness probe |\n| `Integer` | `3307` |\n| [`kompose.service.healthcheck.readiness.test`](#komposeservicehealthcheckreadinesstest) | Command or script run by the readiness probe |\n| `Array` | `[\"CMD\", \"echo\", \"OK\"]` |\n| [`kompose.service.healthcheck.readiness.timeout`](#komposeservicehealthcheckreadinesstimeout) | Timeout for a single readiness probe |\n| `Duration` | `5s` |\n| [`kompose.service.nodeport.port`](#komposeservicenodeportport) | Specific port number to be used as NodePort |\n| `Integer` | `30000` |\n| [`kompose.service.type`](#komposeservicetype) | Type of service |\n| `String` | `nodeport`, `clusterip`, `loadbalancer`, `headless` |\n| [`kompose.volume.size`](#komposevolumesize) | Size of the volume |\n| `String` | `1Gi` |\n| [`kompose.volume.storage-class-name`](#komposevolumestorage-class-name) | StorageClassName for provisioning volumes |\n| `String` | `standard` |\n| [`kompose.volume.subpath`](#komposevolumesubpath) | Subpath inside the mounted volume |\n| `String` | `/data` |\n| [`kompose.volume.type`](#komposevolumetype) | Type of Kubernetes volume |\n| `String` | `configMap`, `persistentVolumeClaim`, `emptyDir`, `hostPath` |\n\n### kompose.controller.port.expose\n\n```yaml\nservices:\n  web:\n    image: wordpress:latest\n    ports:\n      - '80:80'\n    labels:\n      kompose.controller.expose.port: true\n```\n\n### kompose.controller.type\n\n```yaml\nservices:\n  web:\n    image: wordpress:latest\n    ports:\n      - '80:80'\n    labels:\n      kompose.controller.type: deployment\n```\n\n### kompose.cronjob.backoff_limit\n\n```yaml\nservices:\n  cron-job:\n    image: busybox\n    labels:\n      kompose.cronjob.backoff_limit: 3\n```\n\n### kompose.cronjob.concurrency_policy\n\n```yaml\nservices:\n  periodic-task:\n    image: busybox\n    labels:\n      kompose.cronjob.concurrency_policy: Forbid\n```\n\n### kompose.cronjob.schedule\n\n```yaml\nservices:\n  cron-job:\n    image: busybox\n    labels:\n      kompose.cronjob.schedule: \"*/5 * * * *\"\n```\n\n### kompose.hpa.cpu\n\n```yaml\nservices:\n  web:\n    image: nginx\n    labels:\n      kompose.hpa.cpu: 80\n```\n\n### kompose.hpa.memory\n\n```yaml\nservices:\n  db:\n    image: mysql\n    labels:\n      kompose.hpa.memory: 512Mi\n```\n\n### kompose.hpa.replicas.max\n\n```yaml\nservices:\n  api:\n    image: custom-api\n    labels:\n      kompose.hpa.replicas.max: 10\n```\n\n### kompose.hpa.replicas.min\n\n```yaml\nservices:\n  api:\n    image: custom-api\n    labels:\n      kompose.hpa.replicas.min: 2\n```\n\n### kompose.image-pull-policy\n\n```yaml\nservices:\n  example-service:\n    image: example-image\n    labels:\n      kompose.image-pull-policy: \"IfNotPresent\"\n```\n\n### kompose.image-pull-secret\n\n```yaml\nservices:\n  private-service:\n    image: private-repo/image:tag\n    labels:\n      kompose.image-pull-secret: \"my-private-registry-key\"\n```\n\n### kompose.init.containers.command\n\n```yaml\nservices:\n  init-service:\n    image: busybox\n    labels:\n      kompose.init.containers.command: [\"echo\", \"Initializing...\"]\n```\n\n### kompose.init.containers.image\n\n```yaml\nservices:\n  init-service:\n    image: busybox\n    labels:\n      kompose.init.containers.image: busybox\n```\n\n### kompose.init.containers.name\n\n```yaml\nservices:\n  init-service:\n    image: busybox\n    labels:\n      kompose.init.containers.name: \"initial-setup\"\n```\n\n### kompose.security-context.fsgroup\n\n```yaml\nservices:\n  secured-service:\n    image: nginx\n    labels:\n      kompose.security-context.fsgroup: 2000\n```\n\n### kompose.service.external-traffic-policy\n\n```yaml\nservices:\n  front-end:\n    image: quay.io/kompose/web\n    ports:\n      - 8080:8080\n    labels:\n      kompose.service.external-traffic-policy: local\n```\n\n### kompose.service.expose\n\n```yaml\nservices:\n  web-app:\n    image: nginx\n    ports:\n      - 80:80\n    labels:\n      kompose.service.expose: \"example.com\"\n```\n\n### kompose.service.expose.ingress-class-name\n\n```yaml\nservices:\n  web:\n    image: nginx\n    ports:\n      - 80:80\n    labels:\n      kompose.service.expose.ingress-class-name: \"nginx\"\n```\n\n### kompose.service.expose.tls-secret\n\n```yaml\nservices:\n  web:\n    image: nginx\n    ports:\n      - 443:443\n    labels:\n      kompose.service.expose.tls-secret: \"my-ssl-secret\"\n```\n\n### kompose.service.group\n\n```yaml\nversion: \"3\"\n\nservices:\n  nginx:\n    image: nginx\n    depends_on:\n      - logs\n    labels:\n      - kompose.service.group=sidecar\n\n  logs:\n    image: busybox\n    command: [\"tail -f /var/log/nginx/access.log\"]\n    labels:\n      - kompose.service.group=sidecar\n```\n\n### kompose.service.healthcheck.liveness.http_get_path\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    ports:\n      - \"8080:8080\"\n    labels:\n      kompose.service.healthcheck.liveness.http_get_path: /health\n```\n\n### kompose.service.healthcheck.liveness.http_get_port\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    ports:\n      - \"8080:8080\"\n    labels:\n      kompose.service.healthcheck.liveness.http_get_port: 8080\n```\n\n### kompose.service.healthcheck.liveness.tcp_port\n\n```yaml\nservices:\n  db:\n    image: mysql\n    ports:\n      - \"3306:3306\"\n    labels:\n      kompose.service.healthcheck.liveness.tcp_port: 3306\n```\n\n### kompose.service.healthcheck.readiness.disable\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.disable: true\n```\n\n### kompose.service.healthcheck.readiness.http_get_path\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.http_get_path: /ready\n```\n\n### kompose.service.healthcheck.readiness.http_get_port\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.http_get_port: 8081\n```\n\n### kompose.service.healthcheck.readiness.interval\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.interval: 10s\n```\n\n### kompose.service.healthcheck.readiness.retries\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.retries: 3\n```\n\n### kompose.service.healthcheck.readiness.start_period\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.start_period: 30s\n```\n\n### kompose.service.healthcheck.readiness.tcp_port\n\n```yaml\nservices:\n  db:\n    image: mysql\n    labels:\n      kompose.service.healthcheck.readiness.tcp_port: 3307\n```\n\n### kompose.service.healthcheck.readiness.test\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8081/ready\"]\n```\n\n### kompose.service.healthcheck.readiness.timeout\n\n```yaml\nservices:\n  web:\n    image: custom-web\n    labels:\n      kompose.service.healthcheck.readiness.timeout: 5s\n```\n\n### kompose.service.nodeport.port\n\n```yaml\nservices:\n  web:\n    image: nginx\n    ports:\n      - \"30000:80\"\n    labels:\n      kompose.service.nodeport.port: 30000\n```\n\n### kompose.service.type\n\n```yaml\nservices:\n  web:\n    image: nginx\n    ports:\n      - \"80:80\"\n    labels:\n      kompose.service.type: nodeport\n```\n\n### kompose.volume.size\n\n```yaml\nservices:\n  db:\n    image: postgres:10.1\n    labels:\n      kompose.volume.size: 1Gi\n    volumes:\n      - db-data:/var/lib/postgresql/data\n```\n\n### kompose.volume.storage-class-name\n\n```yaml\nservices:\n  db:\n    image: postgres:10.1\n    labels:\n      kompose.volume.storage-class-name: custom-storage-class-name\n    volumes:\n      - db-data:/var/lib/postgresql/data\n```\n\n### kompose.volume.subpath\n\n```yaml\nservices:\n  pgadmin:\n    image: postgres\n    labels:\n      kompose.volume.subpath: pg-data\n```\n\n### kompose.volume.type\n\n```yaml\nservices:\n  db:\n    image: postgres\n    labels:\n      kompose.volume.type: persistentVolumeClaim\n    volumes:\n      - db-data:/var/lib/postgresql/data\n```\n\n## Restart Policy\n\nIf you want to create normal pods without a controller you can use the `restart` construct of compose to define that. Follow the table below to see what happens on the `restart` value.\n\n| `compose` `restart` | object created    | Pod `restartPolicy` |\n|---------------------|-------------------|---------------------|\n| `\"\"`                | controller object | `Always`            |\n| `always`            | controller object | `Always`            |\n| `unless-stopped`    | controller object | `Always`            |\n| `on-failure`        | Pod / CronJob     | `OnFailure`         |\n| `no`                | Pod / CronJob     | `Never`             |\n\n**Note**: controller object could be `deployment`, `replicationcontroller`, etc.\n\nFor example, the `pival` service will become a pod down here. This container calculated the value of `pi`.\n\n```yaml\nversion: '2'\n\nservices:\n  pival:\n    image: perl\n    command: [\"perl\",  \"-Mbignum=bpi\", \"-wle\", \"print bpi(2000)\"]\n    restart: \"on-failure\"\n```\n\nFor example, the `pival` service will become a cron job down here. This container calculated the value of `pi` every minute.\n\n```yaml\nversion: '2'\n\nservices:\n  pival:\n    image: perl\n    command: [\"perl\",  \"-Mbignum=bpi\", \"-wle\", \"print bpi(2000)\"]\n    restart: \"no\"\n    labels:\n      kompose.cronjob.schedule: \"* * * * *\"\n      kompose.cronjob.concurrency_policy: \"Forbid\"\n      kompose.cronjob.backoff_limit: \"0\"\n```\n\n#### Warning about Deployment Configs\n\nIf the Compose file has a volume specified for a service, the Deployment (Kubernetes) or DeploymentConfig (OpenShift) strategy is changed to \"Recreate\" instead of \"RollingUpdate\" (default). This is done to avoid multiple instances of a service from accessing a volume at the same time.\n\nIf the Compose file has a service name with `_` or `.` in it (e.g., `web_service` or `web.service`), then it will be replaced by `-` and the service name will be renamed accordingly (e.g., `web-service`). Kompose does this because \"Kubernetes\" doesn't allow `_` in object names.\n\nPlease note that changing the service name might break some `compose` files.\n\n## Building and Pushing Images\n\nIf the Compose file has `build` or `build:context, build:dockerfile` keys, build will run when `--build` specified.\n\nAnd Image will push to _docker.io_ (default) when `--push-image=true` specified.\n\nIt is possible to push to a custom registry by specifying `--push-image-registry`, which will override the registry from the image name.\n\n### Authentication on Registry\n\nKompose uses the docker authentication from file `$DOCKER_CONFIG/config.json`, `$HOME/.docker/config.json`, and `$HOME/.dockercfg` after `docker login`.\n\n**This only works fine on Linux but macOS would fail when using `\"credsStore\": \"osxkeychain\"`.**\n\nHowever, there is an approach to push successfully on macOS, by not using `osxkeychain` for `credsStore`. To disable `osxkeychain`:\n\n- remove `credsStore` from the `config.json` file, and `docker login` again.\n- for some docker desktop versions, there is a setting `Securely store Docker logins in macOS keychain`, which should be unchecked. Then restart docker desktop if needed, and `docker login` again.\n\nNow `config.json` should contain base64 encoded passwords, then push image should succeed. Working, but not safe though! Use it at your risk.\n\nFor Windows, there is also `credsStore` which is `wincred`. Technically it will fail on authentication as macOS does, but you can try the approach above like macOS too.\n\n### Custom Build and Push\n\nIf you want to customize the build and push processes and use another containers solution than Docker,\nKompose offers you the possibility to do that. You can use `--build-command` and `--push-command` flags\nto achieve that.\n\ne.g: `kompose -f convert --build-command 'whatever command --you-use' --push-command 'whatever command --you-use'`\n"
  },
  {
    "path": "examples/compose.yaml",
    "content": "services:\n\n  redis-leader:\n    container_name: redis-leader\n    image: redis\n    ports:\n      - \"6379\"\n\n  redis-replica:\n    container_name: redis-replica\n    image: redis\n    ports:\n      - \"6379\"\n    command: redis-server --replicaof redis-leader 6379 --dir /tmp\n\n  web:\n    container_name: web\n    image: quay.io/kompose/web\n    ports:\n      - \"8080:8080\""
  },
  {
    "path": "examples/web/Dockerfile",
    "content": "FROM golang:1.21.2\n\n# Debugging within the container\nRUN apt-get update && apt-get install dnsutils redis-tools -y\n\n# Set the working directory in the container\nWORKDIR /app\n\n# Copy the entire project which includes the public directory, vendoring, etc.\nCOPY . .\n\n# Build your application\nRUN CGO_ENABLED=0 GOOS=linux go build -o /frontend\n\n# Change the permissions so that all users can execute it\nRUN chmod +x /frontend\n\n# Although setting permissions on /frontend should suffice, set wider permissions if needed\nRUN chown -R 1001:0 /app && \\\n    chmod -R g=u /app\n\n# This directive ensures the container does not run as root\nUSER 1001\n\nEXPOSE 8080\nCMD [\"/frontend\"]\n"
  },
  {
    "path": "examples/web/README.md",
    "content": "A fork of https://github.com/kubernetes/examples/blob/master/guestbook-go/README.md\n\nA simple example that shows the functionality of Kompose\n\nPushed to https://docker.io/kompose/web\n"
  },
  {
    "path": "examples/web/compose.yaml",
    "content": "services:\n\n  redis-leader:\n    container_name: redis-leader\n    image: redis\n    ports:\n      - \"6379\"\n\n  redis-replica:\n    container_name: redis-replica\n    image: redis\n    ports:\n      - \"6379\"\n    command: redis-server --replicaof redis-leader 6379\n\n  web:\n    container_name: web\n    build: ./web\n    ports:\n      - \"8080:8080\"\n"
  },
  {
    "path": "examples/web/go.mod",
    "content": "module github.com/redhat-developer/podman-desktop-demo\n\ngo 1.21.2\n\nrequire (\n\tgithub.com/codegangsta/negroni v1.0.0\n\tgithub.com/gorilla/mux v1.8.1\n\tgithub.com/xyproto/simpleredis/v2 v2.6.5\n)\n\nrequire (\n\tgithub.com/gomodule/redigo v1.8.9 // indirect\n\tgithub.com/xyproto/pinterface v1.5.3 // indirect\n)\n"
  },
  {
    "path": "examples/web/go.sum",
    "content": "github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=\ngithub.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=\ngithub.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=\ngithub.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=\ngithub.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=\ngithub.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=\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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/xyproto/pinterface v1.5.3 h1:RKkNT88cwrSqD9hU4cYAO5yeo8srg4TG+74Pcj88iz0=\ngithub.com/xyproto/pinterface v1.5.3/go.mod h1:X5B5pKE49ak7SpyDh5QvJvLH9cC9XuZNDcl5hEyYc34=\ngithub.com/xyproto/simpleredis/v2 v2.6.5 h1:PtAz5j2UUACNHx5LetI60dbCsVMhIv1H878bND4VQK4=\ngithub.com/xyproto/simpleredis/v2 v2.6.5/go.mod h1:OrWVubZGr0SbpAjkAQkFn/iiex2AsblBm80uhYxbjQY=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "examples/web/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/codegangsta/negroni\"\n\t\"github.com/gorilla/mux\"\n\t\"github.com/xyproto/simpleredis/v2\"\n)\n\nvar (\n\tleaderPool   *simpleredis.ConnectionPool\n\treplicaPools []*simpleredis.ConnectionPool\n)\n\nfunc ListRangeHandler(rw http.ResponseWriter, req *http.Request) {\n\tkey := mux.Vars(req)[\"key\"]\n\tvar members []string\n\tvar err error\n\tfor _, replicaPool := range replicaPools {\n\t\tlist := simpleredis.NewList(replicaPool, key)\n\t\tmembers, err = list.GetAll()\n\t\tif err == nil {\n\t\t\tbreak // Found a replica with data, exit loop\n\t\t}\n\t}\n\tif err != nil {\n\t\thttp.Error(rw, \"Failed to retrieve data from replicas\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tmembersJSON, err := json.MarshalIndent(members, \"\", \"  \")\n\tif err != nil {\n\t\thttp.Error(rw, \"Failed to marshal JSON\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\trw.Write(membersJSON)\n}\n\nfunc ListPushHandler(rw http.ResponseWriter, req *http.Request) {\n\tkey := mux.Vars(req)[\"key\"]\n\tvalue := mux.Vars(req)[\"value\"]\n\tlist := simpleredis.NewList(leaderPool, key)\n\tHandleError(nil, list.Add(value))\n\tListRangeHandler(rw, req)\n}\n\nfunc InfoHandler(rw http.ResponseWriter, req *http.Request) {\n\tinfo := HandleError(leaderPool.Get(0).Do(\"INFO\")).([]byte)\n\trw.Write(info)\n}\n\nfunc EnvHandler(rw http.ResponseWriter, req *http.Request) {\n\tenvironment := make(map[string]string)\n\tfor _, item := range os.Environ() {\n\t\tsplits := strings.Split(item, \"=\")\n\t\tkey := splits[0]\n\t\tval := strings.Join(splits[1:], \"=\")\n\t\tenvironment[key] = val\n\t}\n\n\tenvJSON := HandleError(json.MarshalIndent(environment, \"\", \"  \")).([]byte)\n\trw.Write(envJSON)\n}\n\nfunc HandleError(result interface{}, err error) (r interface{}) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn result\n}\n\nfunc getReplicaPool() *simpleredis.ConnectionPool {\n\t// Use the first replica as the primary replica for read operations\n\treturn replicaPools[0]\n}\n\nfunc main() {\n\t// Read the Redis replica addresses from an environment variable\n\treplicaAddresses := os.Getenv(\"REDIS_REPLICAS\")\n\tif replicaAddresses == \"\" {\n\t\t// Use default values if not set\n\t\treplicaAddresses = \"redis-replica\"\n\t}\n\n\t// Read the Redis port number from an environment variable\n\tredisPort := os.Getenv(\"REDIS_PORT\")\n\tif redisPort == \"\" {\n\t\t// Use default port if not set\n\t\tredisPort = \"6379\"\n\t}\n\n\t// Read the Redis leader address from an environment variable\n\tredisLeaderAddress := os.Getenv(\"REDIS_LEADER\")\n\tif redisLeaderAddress == \"\" {\n\t\t// Use default leader address if not set\n\t\tredisLeaderAddress = \"redis-leader\"\n\t}\n\n\t// Read the server port number from an environment variable\n\tserverPort := os.Getenv(\"SERVER_PORT\")\n\tif serverPort == \"\" {\n\t\t// Use default port if not set\n\t\tserverPort = \"8080\"\n\t}\n\n\t// Construct the Redis leader and replica addresses\n\tleaderAddress := redisLeaderAddress + \":\" + redisPort\n\treplicaAddressesArr := strings.Split(replicaAddresses, \",\")\n\treplicaPools = make([]*simpleredis.ConnectionPool, len(replicaAddressesArr))\n\tfor i, addr := range replicaAddressesArr {\n\t\treplicaPools[i] = simpleredis.NewConnectionPoolHost(addr + \":\" + redisPort)\n\t\tdefer replicaPools[i].Close()\n\t}\n\n\t// Create a connection pool for the leader using the constructed address\n\tleaderPool = simpleredis.NewConnectionPoolHost(leaderAddress)\n\tdefer leaderPool.Close()\n\n\tr := mux.NewRouter()\n\tr.Path(\"/lrange/{key}\").Methods(\"GET\").HandlerFunc(ListRangeHandler)\n\tr.Path(\"/rpush/{key}/{value}\").Methods(\"GET\").HandlerFunc(ListPushHandler)\n\tr.Path(\"/info\").Methods(\"GET\").HandlerFunc(InfoHandler)\n\tr.Path(\"/env\").Methods(\"GET\").HandlerFunc(EnvHandler)\n\n\tn := negroni.Classic()\n\tn.UseHandler(r)\n\tn.Run(\":\" + serverPort)\n}\n"
  },
  {
    "path": "examples/web/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta content=\"text/html; charset=utf-8\" http-equiv=\"Content-Type\">\n    <meta charset=\"utf-8\">\n    <meta content=\"width=device-width\" name=\"viewport\">\n    <link href=\"style.css\" rel=\"stylesheet\">\n    <title>Kompose Guestbook</title>\n  </head>\n  <body>\n    <div id=\"header\">\n      <img src=\"logo.png\" width=\"300px\">\n      <h1>Kompose Guestbook</h1>\n    </div>\n\n    <div id=\"guestbook-entries\">\n      <p>Waiting for database connection...</p>\n    </div>\n\n    <div>\n      <form id=\"guestbook-form\">\n        <input autocomplete=\"off\" id=\"guestbook-entry-content\" type=\"text\">\n        <a href=\"#\" id=\"guestbook-submit\">Submit</a>\n      </form>\n    </div>\n\n    <div>\n      <p><h2 id=\"guestbook-host-address\"></h2></p>\n      <p><a href=\"env\">/env</a>\n      <a href=\"info\">/info</a></p>\n    </div>\n    <script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js\"></script>\n    <script src=\"script.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/web/public/script.js",
    "content": "$(document).ready(function() {\n  var headerTitleElement = $(\"#header h1\");\n  var entriesElement = $(\"#guestbook-entries\");\n  var formElement = $(\"#guestbook-form\");\n  var submitElement = $(\"#guestbook-submit\");\n  var entryContentElement = $(\"#guestbook-entry-content\");\n  var hostAddressElement = $(\"#guestbook-host-address\");\n\n  var appendGuestbookEntries = function(data) {\n    entriesElement.empty();\n    $.each(data, function(key, val) {\n      entriesElement.append(\"<p>\" + val + \"</p>\");\n    });\n  }\n// On submission, clear the input field and add the entry to the guestbook.\n  var handleSubmission = function(e) {\n    e.preventDefault();\n    var entryValue = entryContentElement.val()\n    if (entryValue.length > 0) {\n      entriesElement.append(\"<p>...</p>\");\n      $.getJSON(\"rpush/guestbook/\" + entryValue, appendGuestbookEntries);\n    }\n    // Clear entryContentElement input field on click.\n    entryContentElement.val(\"\");\n    return false;\n  }\n\n  var colors = [\"#1f77b4\", \"#2ca02c\", \"#d62728\", \"#9467bd\", \"#ff7f0e\"];\n  var randomColor = colors[Math.floor(5 * Math.random())];\n  (function setElementsColor(color) {\n    headerTitleElement.css(\"color\", color);\n    entryContentElement.css(\"box-shadow\", \"inset 0 0 0 2px \" + color);\n    submitElement.css(\"background-color\", color);\n  })(randomColor);\n\n  submitElement.click(handleSubmission);\n  formElement.submit(handleSubmission);\n  hostAddressElement.append(document.URL);\n\n  // Poll every second.\n  (function fetchGuestbook() {\n    $.getJSON(\"lrange/guestbook\").done(appendGuestbookEntries).always(\n      function() {\n        setTimeout(fetchGuestbook, 1000);\n      });\n  })();\n});\n"
  },
  {
    "path": "examples/web/public/style.css",
    "content": "body, input {\n  color: #123;\n  font-family: \"Gill Sans\", sans-serif;\n}\n\ndiv {\n  overflow: hidden;\n  padding: 1em 0;\n  position: relative;\n  text-align: center;\n}\n\nh1, h2, p, input, a {\n  font-weight: 300;\n  margin: 0;\n}\n\nh1 {\n  color: #BDB76B;\n  font-size: 3.5em;\n}\n\nh2 {\n  color: #999;\n}\n\nform {\n  margin: 0 auto;\n  max-width: 50em;\n  text-align: center;\n}\n\ninput {\n  border: 0;\n  border-radius: 1000px;\n  box-shadow: inset 0 0 0 2px #BDB76B;\n  display: inline;\n  font-size: 1.5em;\n  margin-bottom: 1em;\n  outline: none;\n  padding: .5em 5%;\n  width: 55%;\n}\n\nform a {\n  background: #BDB76B;\n  border: 0;\n  border-radius: 1000px;\n  color: #FFF;\n  font-size: 1.25em;\n  font-weight: 400;\n  padding: .75em 2em;\n  text-decoration: none;\n  text-transform: uppercase;\n  white-space: normal;\n}\n\np {\n  font-size: 1.5em;\n  line-height: 1.5;\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/.gitignore",
    "content": "/coverage.txt\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/.travis.yml",
    "content": "language: go\n\nsudo: false\ndist: trusty\n\ngo:\n- 1.x\n- 1.2.x\n- 1.3.x\n- 1.4.x\n- 1.5.x\n- 1.6.x\n- 1.7.x\n- 1.8.x\n- master\n\nbefore_install:\n- find \"${GOPATH%%:*}\" -name '*.a' -delete\n- rm -rf \"${GOPATH%%:*}/src/golang.org\"\n- go get golang.org/x/tools/cover\n- go get golang.org/x/tools/cmd/cover\n\nscript:\n- go test -race -coverprofile=coverage.txt -covermode=atomic\n\nafter_success:\n- bash <(curl -s \"https://codecov.io/bash\")\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/CHANGELOG.md",
    "content": "# Change Log\n\n**ATTN**: This project uses [semantic versioning](http://semver.org/).\n\n## [Unreleased] -\n\n## [1.0.0] - 2018-09-01\n\n### Fixed\n- `Logger` middleware now correctly handles paths containing a `%` instead of trying to treat it as a format specifier\n\n## [0.3.0] - 2017-11-11\n### Added\n- `With()` helper for building a new `Negroni` struct chaining handlers from\n  existing `Negroni` structs\n- Format log output in `Logger` middleware via a configurable `text/template`\n  string injectable via `.SetFormat`. Added `LoggerDefaultFormat` and\n  `LoggerDefaultDateFormat` to configure the default template and date format\n  used by the `Logger` middleware.\n- Support for HTTP/2 pusher support via `http.Pusher` interface for Go 1.8+.\n- `WrapFunc` to convert `http.HandlerFunc` into a `negroni.Handler`\n- `Formatter` field added to `Recovery` middleware to allow configuring how\n  `panic`s are output. Default of `TextFormatter` (how it was output in\n  `0.2.0`) used. `HTMLPanicFormatter` also added to allow easy outputing of\n  `panic`s as HTML.\n\n### Fixed\n- `Written()` correct returns `false` if no response header has been written\n- Only implement `http.CloseNotifier` with the `negroni.ResponseWriter` if the\n  underlying `http.ResponseWriter` implements it (previously would always\n  implement it and panic if the underlying `http.ResponseWriter` did not.\n\n### Changed\n- Set default status to `0` in the case that no handler writes status -- was\n  previously `200` (in 0.2.0, before that it was `0` so this reestablishes that\n  behavior)\n- Catch `panic`s thrown by callbacks provided to the `Recovery` handler\n- Recovery middleware will set `text/plain` content-type if none is set\n- `ALogger` interface to allow custom logger outputs to be used with the\n  `Logger` middleware. Changes embeded field in `negroni.Logger` from `Logger`\n  to `ALogger`.\n- Default `Logger` middleware output changed to be more structure and verbose\n  (also now configurable, see `Added`)\n- Automatically bind to port specified in `$PORT` in `.Run()` if an address is\n  not passed in. Fall back to binding to `:8080` if no address specified\n  (configuable via `DefaultAddress`).\n- `PanicHandlerFunc` added to `Recovery` middleware to enhance custom handling\n  of `panic`s by providing additional information to the handler including the\n  stack and the `http.Request`. `Recovery.ErrorHandlerFunc` was also added, but\n  deprecated in favor of the new `PanicHandlerFunc`.\n\n## [0.2.0] - 2016-05-10\n### Added\n- Support for variadic handlers in `New()`\n- Added `Negroni.Handlers()` to fetch all of the handlers for a given chain\n- Allowed size in `Recovery` handler was bumped to 8k\n- `Negroni.UseFunc` to push another handler onto the chain\n\n### Changed\n- Set the status before calling `beforeFuncs` so the information is available to them\n- Set default status to `200` in the case that no handler writes status -- was previously `0`\n- Panic if `nil` handler is given to `negroni.Use`\n\n## 0.1.0 - 2013-07-22\n### Added\n- Initial implementation.\n\n[Unreleased]: https://github.com/urfave/negroni/compare/v0.2.0...HEAD\n[0.2.0]: https://github.com/urfave/negroni/compare/v0.1.0...v0.2.0\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Jeremy Saenz\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 all\ncopies 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 THE\nSOFTWARE.\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/README.md",
    "content": "# Negroni\n[![GoDoc](https://godoc.org/github.com/urfave/negroni?status.svg)](http://godoc.org/github.com/urfave/negroni)\n[![Build Status](https://travis-ci.org/urfave/negroni.svg?branch=master)](https://travis-ci.org/urfave/negroni)\n[![codebeat](https://codebeat.co/badges/47d320b1-209e-45e8-bd99-9094bc5111e2)](https://codebeat.co/projects/github-com-urfave-negroni)\n[![codecov](https://codecov.io/gh/urfave/negroni/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/negroni)\n\n**Notice:** This is the library formerly known as\n`github.com/codegangsta/negroni` -- Github will automatically redirect requests\nto this repository, but we recommend updating your references for clarity.\n\nNegroni is an idiomatic approach to web middleware in Go. It is tiny,\nnon-intrusive, and encourages use of `net/http` Handlers.\n\nIf you like the idea of [Martini](https://github.com/go-martini/martini), but\nyou think it contains too much magic, then Negroni is a great fit.\n\nLanguage Translations:\n* [Deutsch (de_DE)](translations/README_de_de.md)\n* [Português Brasileiro (pt_BR)](translations/README_pt_br.md)\n* [简体中文 (zh_CN)](translations/README_zh_CN.md)\n* [繁體中文 (zh_TW)](translations/README_zh_tw.md)\n* [日本語 (ja_JP)](translations/README_ja_JP.md)\n* [Français (fr_FR)](translations/README_fr_FR.md)\n\n## Getting Started\n\nAfter installing Go and setting up your\n[GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file.\nWe'll call it `server.go`.\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  n := negroni.Classic() // Includes some default middlewares\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3000\", n)\n}\n```\n\nThen install the Negroni package (**NOTE**: &gt;= **go 1.1** is required):\n\n```\ngo get github.com/urfave/negroni\n```\n\nThen run your server:\n\n```\ngo run server.go\n```\n\nYou will now have a Go `net/http` webserver running on `localhost:3000`.\n\n### Packaging\n\nIf you are on Debian, `negroni` is also available as [a\npackage](https://packages.debian.org/sid/golang-github-urfave-negroni-dev) that\nyou can install via `apt install golang-github-urfave-negroni-dev` (at the time\nof writing, it is in the `sid` repositories).\n\n## Is Negroni a Framework?\n\nNegroni is **not** a framework. It is a middleware-focused library that is\ndesigned to work directly with `net/http`.\n\n## Routing?\n\nNegroni is BYOR (Bring your own Router). The Go community already has a number\nof great http routers available, and Negroni tries to play well with all of them\nby fully supporting `net/http`. For instance, integrating with [Gorilla Mux]\nlooks like so:\n\n``` go\nrouter := mux.NewRouter()\nrouter.HandleFunc(\"/\", HomeHandler)\n\nn := negroni.New(Middleware1, Middleware2)\n// Or use a middleware with the Use() function\nn.Use(Middleware3)\n// router goes last\nn.UseHandler(router)\n\nhttp.ListenAndServe(\":3001\", n)\n```\n\n## `negroni.Classic()`\n\n`negroni.Classic()` provides some default middleware that is useful for most\napplications:\n\n* [`negroni.Recovery`](#recovery) - Panic Recovery Middleware.\n* [`negroni.Logger`](#logger) - Request/Response Logger Middleware.\n* [`negroni.Static`](#static) - Static File serving under the \"public\"\n  directory.\n\nThis makes it really easy to get started with some useful features from Negroni.\n\n## Handlers\n\nNegroni provides a bidirectional middleware flow. This is done through the\n`negroni.Handler` interface:\n\n``` go\ntype Handler interface {\n  ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)\n}\n```\n\nIf a middleware hasn't already written to the `ResponseWriter`, it should call\nthe next `http.HandlerFunc` in the chain to yield to the next middleware\nhandler.  This can be used for great good:\n\n``` go\nfunc MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n  // do some stuff before\n  next(rw, r)\n  // do some stuff after\n}\n```\n\nAnd you can map it to the handler chain with the `Use` function:\n\n``` go\nn := negroni.New()\nn.Use(negroni.HandlerFunc(MyMiddleware))\n```\n\nYou can also map plain old `http.Handler`s:\n\n``` go\nn := negroni.New()\n\nmux := http.NewServeMux()\n// map your routes\n\nn.UseHandler(mux)\n\nhttp.ListenAndServe(\":3000\", n)\n```\n\n## `With()`\n\nNegroni has a convenience function called `With`. `With` takes one or more\n`Handler` instances and returns a new `Negroni` with the combination of the\nreceiver's handlers and the new handlers.\n\n```go\n// middleware we want to reuse\ncommon := negroni.New()\ncommon.Use(MyMiddleware1)\ncommon.Use(MyMiddleware2)\n\n// `specific` is a new negroni with the handlers from `common` combined with the\n// the handlers passed in\nspecific := common.With(\n\tSpecificMiddleware1,\n\tSpecificMiddleware2\n)\n```\n\n## `Run()`\n\nNegroni has a convenience function called `Run`. `Run` takes an addr string\nidentical to [`http.ListenAndServe`](https://godoc.org/net/http#ListenAndServe).\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  n := negroni.Classic()\n  n.Run(\":8080\")\n}\n```\nIf no address is provided, the `PORT` environment variable is used instead.\nIf the `PORT` environment variable is not defined, the default address will be used. \nSee [Run](https://godoc.org/github.com/urfave/negroni#Negroni.Run) for a complete description.\n\nIn general, you will want to use `net/http` methods and pass `negroni` as a\n`Handler`, as this is more flexible, e.g.:\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"log\"\n  \"net/http\"\n  \"time\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  n := negroni.Classic() // Includes some default middlewares\n  n.UseHandler(mux)\n\n  s := &http.Server{\n    Addr:           \":8080\",\n    Handler:        n,\n    ReadTimeout:    10 * time.Second,\n    WriteTimeout:   10 * time.Second,\n    MaxHeaderBytes: 1 << 20,\n  }\n  log.Fatal(s.ListenAndServe())\n}\n```\n\n## Route Specific Middleware\n\nIf you have a route group of routes that need specific middleware to be\nexecuted, you can simply create a new Negroni instance and use it as your route\nhandler.\n\n``` go\nrouter := mux.NewRouter()\nadminRoutes := mux.NewRouter()\n// add admin routes here\n\n// Create a new negroni for the admin middleware\nrouter.PathPrefix(\"/admin\").Handler(negroni.New(\n  Middleware1,\n  Middleware2,\n  negroni.Wrap(adminRoutes),\n))\n```\n\nIf you are using [Gorilla Mux], here is an example using a subrouter:\n\n``` go\nrouter := mux.NewRouter()\nsubRouter := mux.NewRouter().PathPrefix(\"/subpath\").Subrouter().StrictSlash(true)\nsubRouter.HandleFunc(\"/\", someSubpathHandler) // \"/subpath/\"\nsubRouter.HandleFunc(\"/:id\", someSubpathHandler) // \"/subpath/:id\"\n\n// \"/subpath\" is necessary to ensure the subRouter and main router linkup\nrouter.PathPrefix(\"/subpath\").Handler(negroni.New(\n  Middleware1,\n  Middleware2,\n  negroni.Wrap(subRouter),\n))\n```\n\n`With()` can be used to eliminate redundancy for middlewares shared across\nroutes.\n\n``` go\nrouter := mux.NewRouter()\napiRoutes := mux.NewRouter()\n// add api routes here\nwebRoutes := mux.NewRouter()\n// add web routes here\n\n// create common middleware to be shared across routes\ncommon := negroni.New(\n\tMiddleware1,\n\tMiddleware2,\n)\n\n// create a new negroni for the api middleware\n// using the common middleware as a base\nrouter.PathPrefix(\"/api\").Handler(common.With(\n  APIMiddleware1,\n  negroni.Wrap(apiRoutes),\n))\n// create a new negroni for the web middleware\n// using the common middleware as a base\nrouter.PathPrefix(\"/web\").Handler(common.With(\n  WebMiddleware1,\n  negroni.Wrap(webRoutes),\n))\n```\n\n## Bundled Middleware\n\n### Static\n\nThis middleware will serve files on the filesystem. If the files do not exist,\nit proxies the request to the next middleware. If you want the requests for\nnon-existent files to return a `404 File Not Found` to the user you should look\nat using [http.FileServer](https://golang.org/pkg/net/http/#FileServer) as\na handler.\n\nExample:\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  // Example of using a http.FileServer if you want \"server-like\" rather than \"middleware\" behavior\n  // mux.Handle(\"/public\", http.FileServer(http.Dir(\"/home/public\")))\n\n  n := negroni.New()\n  n.Use(negroni.NewStatic(http.Dir(\"/tmp\")))\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3002\", n)\n}\n```\n\nWill serve files from the `/tmp` directory first, but proxy calls to the next\nhandler if the request does not match a file on the filesystem.\n\n### Recovery\n\nThis middleware catches `panic`s and responds with a `500` response code. If\nany other middleware has written a response code or body, this middleware will\nfail to properly send a 500 to the client, as the client has already received\nthe HTTP response code. Additionally, an `PanicHandlerFunc` can be attached\nto report 500's to an error reporting service such as Sentry or Airbrake.\n\nExample:\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"net/http\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    panic(\"oh no\")\n  })\n\n  n := negroni.New()\n  n.Use(negroni.NewRecovery())\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3003\", n)\n}\n```\n\nWill return a `500 Internal Server Error` to each request. It will also log the\nstack traces as well as print the stack trace to the requester if `PrintStack`\nis set to `true` (the default).\n\nExample with error handler:\n\n``` go\npackage main\n\nimport (\n  \"net/http\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    panic(\"oh no\")\n  })\n\n  n := negroni.New()\n  recovery := negroni.NewRecovery()\n  recovery.PanicHandlerFunc = reportToSentry\n  n.Use(recovery)\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3003\", n)\n}\n\nfunc reportToSentry(info *negroni.PanicInformation) {\n    // write code here to report error to Sentry\n}\n```\n\nThe middleware simply output the informations on STDOUT by default.\nYou can customize the output process by using the `SetFormatter()` function.\n\nYou can use also the `HTMLPanicFormatter` to display a pretty HTML when a crash occurs.\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"net/http\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    panic(\"oh no\")\n  })\n\n  n := negroni.New()\n  recovery := negroni.NewRecovery()\n  recovery.Formatter = &negroni.HTMLPanicFormatter{}\n  n.Use(recovery)\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3003\", n)\n}\n```\n\n## Logger\n\nThis middleware logs each incoming request and response.\n\nExample:\n\n<!-- { \"interrupt\": true } -->\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  \"github.com/urfave/negroni\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  n := negroni.New()\n  n.Use(negroni.NewLogger())\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3004\", n)\n}\n```\n\nWill print a log similar to:\n\n```\n[negroni] 2017-10-04T14:56:25+02:00 | 200 |      378µs | localhost:3004 | GET /\n```\n\non each request.\n\nYou can also set your own log format by calling the `SetFormat` function. The format is a template string with fields as mentioned in the `LoggerEntry` struct. So, as an example -\n\n```go\nl.SetFormat(\"[{{.Status}} {{.Duration}}] - {{.Request.UserAgent}}\")\n```\n\nwill show something like - `[200 18.263µs] - Go-User-Agent/1.1 `\n\n## Third Party Middleware\n\nHere is a current list of Negroni compatible middlware. Feel free to put up a PR\nlinking your middleware if you have built one:\n\n| Middleware | Author | Description |\n| -----------|--------|-------------|\n| [authz](https://github.com/casbin/negroni-authz) | [Yang Luo](https://github.com/hsluoyz) | ACL, RBAC, ABAC Authorization middlware based on [Casbin](https://github.com/casbin/casbin) |\n| [binding](https://github.com/mholt/binding) | [Matt Holt](https://github.com/mholt) | Data binding from HTTP requests into structs |\n| [cloudwatch](https://github.com/cvillecsteele/negroni-cloudwatch) | [Colin Steele](https://github.com/cvillecsteele) | AWS cloudwatch metrics middleware |\n| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support |\n| [csp](https://github.com/awakenetworks/csp) | [Awake Networks](https://github.com/awakenetworks) | [Content Security Policy](https://www.w3.org/TR/CSP2/) (CSP) support |\n| [delay](https://github.com/jeffbmartinez/delay) | [Jeff Martinez](https://github.com/jeffbmartinez) | Add delays/latency to endpoints. Useful when testing effects of high latency |\n| [New Relic Go Agent](https://github.com/yadvendar/negroni-newrelic-go-agent) | [Yadvendar Champawat](https://github.com/yadvendar) | Official [New Relic Go Agent](https://github.com/newrelic/go-agent) (currently in beta)  |\n| [gorelic](https://github.com/jingweno/negroni-gorelic) | [Jingwen Owen Ou](https://github.com/jingweno) | New Relic agent for Go runtime |\n| [Graceful](https://github.com/tylerb/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown |\n| [gzip](https://github.com/phyber/negroni-gzip) | [phyber](https://github.com/phyber) | GZIP response compression |\n| [JWT Middleware](https://github.com/auth0/go-jwt-middleware) | [Auth0](https://github.com/auth0) | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it|\n| [JWT Middleware](https://github.com/mfuentesg/go-jwtmiddleware) | [Marcelo Fuentes](https://github.com/mfuentesg) | JWT middleware for golang |\n| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger |\n| [oauth2](https://github.com/goincremental/negroni-oauth2) | [David Bochenski](https://github.com/bochenski) | oAuth2 middleware |\n| [onthefly](https://github.com/xyproto/onthefly) | [Alexander Rødseth](https://github.com/xyproto) | Generate TinySVG, HTML and CSS on the fly |\n| [permissions2](https://github.com/xyproto/permissions2) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, users and permissions |\n| [prometheus](https://github.com/zbindenren/negroni-prometheus) | [Rene Zbinden](https://github.com/zbindenren) | Easily create metrics endpoint for the [prometheus](http://prometheus.io) instrumentation tool |\n| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Render JSON, XML and HTML templates |\n| [RestGate](https://github.com/pjebs/restgate) | [Prasanga Siripala](https://github.com/pjebs) | Secure authentication for REST API endpoints |\n| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Middleware that implements a few quick security wins |\n| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Session Management |\n| [stats](https://github.com/thoas/stats) | [Florent Messa](https://github.com/thoas) | Store information about your web application (response time, etc.) |\n| [VanGoH](https://github.com/auroratechnologies/vangoh) | [Taylor Wrobel](https://github.com/twrobel3) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware |\n| [xrequestid](https://github.com/pilu/xrequestid) | [Andrea Franz](https://github.com/pilu) | Middleware that assigns a random X-Request-Id header to each request |\n| [mgo session](https://github.com/joeljames/nigroni-mgo-session) | [Joel James](https://github.com/joeljames) | Middleware that handles creating and closing mgo sessions per request |\n| [digits](https://github.com/bamarni/digits) | [Bilal Amarni](https://github.com/bamarni) | Middleware that handles [Twitter Digits](https://get.digits.com/) authentication |\n| [stats](https://github.com/guptachirag/stats) | [Chirag Gupta](https://github.com/guptachirag/stats) | Middleware that manages qps and latency stats for your endpoints and asynchronously flushes them to influx db |\n| [Chaos](https://github.com/falzm/chaos) | [Marc Falzon](https://github.com/falzm) | Middleware for injecting chaotic behavior into application in a programmatic way |\n\n## Examples\n\n[Alexander Rødseth](https://github.com/xyproto) created\n[mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a\nNegroni middleware handler.\n\n[Prasanga Siripala](https://github.com/pjebs) created an effective skeleton structure for web-based Go/Negroni projects: [Go-Skeleton](https://github.com/pjebs/go-skeleton) \n\n## Live code reload?\n\n[gin](https://github.com/codegangsta/gin) and\n[fresh](https://github.com/pilu/fresh) both live reload negroni apps.\n\n## Essential Reading for Beginners of Go & Negroni\n\n* [Using a Context to pass information from middleware to end handler](http://elithrar.github.io/article/map-string-interface/)\n* [Understanding middleware](https://mattstauffer.co/blog/laravel-5.0-middleware-filter-style)\n\n## About\n\nNegroni is obsessively designed by none other than the [Code\nGangsta](https://codegangsta.io/)\n\n[Gorilla Mux]: https://github.com/gorilla/mux\n[`http.FileSystem`]: https://godoc.org/net/http#FileSystem\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/doc.go",
    "content": "// Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers.\n//\n// If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit.\n//\n// For a full guide visit http://github.com/urfave/negroni\n//\n//\tpackage main\n//\n//\timport (\n//\t  \"github.com/urfave/negroni\"\n//\t  \"net/http\"\n//\t  \"fmt\"\n//\t)\n//\n//\tfunc main() {\n//\t  mux := http.NewServeMux()\n//\t  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n//\t    fmt.Fprintf(w, \"Welcome to the home page!\")\n//\t  })\n//\n//\t  n := negroni.Classic()\n//\t  n.UseHandler(mux)\n//\t  n.Run(\":3000\")\n//\t}\npackage negroni\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/logger.go",
    "content": "package negroni\n\nimport (\n\t\"bytes\"\n\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"text/template\"\n\t\"time\"\n)\n\n// LoggerEntry is the structure passed to the template.\ntype LoggerEntry struct {\n\tStartTime string\n\tStatus    int\n\tDuration  time.Duration\n\tHostname  string\n\tMethod    string\n\tPath      string\n\tRequest   *http.Request\n}\n\n// LoggerDefaultFormat is the format logged used by the default Logger instance.\nvar LoggerDefaultFormat = \"{{.StartTime}} | {{.Status}} | \\t {{.Duration}} | {{.Hostname}} | {{.Method}} {{.Path}}\"\n\n// LoggerDefaultDateFormat is the format used for date by the default Logger instance.\nvar LoggerDefaultDateFormat = time.RFC3339\n\n// ALogger interface\ntype ALogger interface {\n\tPrintln(v ...interface{})\n\tPrintf(format string, v ...interface{})\n}\n\n// Logger is a middleware handler that logs the request as it goes in and the response as it goes out.\ntype Logger struct {\n\t// ALogger implements just enough log.Logger interface to be compatible with other implementations\n\tALogger\n\tdateFormat string\n\ttemplate   *template.Template\n}\n\n// NewLogger returns a new Logger instance\nfunc NewLogger() *Logger {\n\tlogger := &Logger{ALogger: log.New(os.Stdout, \"[negroni] \", 0), dateFormat: LoggerDefaultDateFormat}\n\tlogger.SetFormat(LoggerDefaultFormat)\n\treturn logger\n}\n\nfunc (l *Logger) SetFormat(format string) {\n\tl.template = template.Must(template.New(\"negroni_parser\").Parse(format))\n}\n\nfunc (l *Logger) SetDateFormat(format string) {\n\tl.dateFormat = format\n}\n\nfunc (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\tstart := time.Now()\n\n\tnext(rw, r)\n\n\tres := rw.(ResponseWriter)\n\tlog := LoggerEntry{\n\t\tStartTime: start.Format(l.dateFormat),\n\t\tStatus:    res.Status(),\n\t\tDuration:  time.Since(start),\n\t\tHostname:  r.Host,\n\t\tMethod:    r.Method,\n\t\tPath:      r.URL.Path,\n\t\tRequest:   r,\n\t}\n\n\tbuff := &bytes.Buffer{}\n\tl.template.Execute(buff, log)\n\tl.Println(buff.String())\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/negroni.go",
    "content": "package negroni\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n)\n\nconst (\n\t// DefaultAddress is used if no other is specified.\n\tDefaultAddress = \":8080\"\n)\n\n// Handler handler is an interface that objects can implement to be registered to serve as middleware\n// in the Negroni middleware stack.\n// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc\n// passed in.\n//\n// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked.\ntype Handler interface {\n\tServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)\n}\n\n// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.\n// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.\ntype HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)\n\nfunc (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\th(rw, r, next)\n}\n\ntype middleware struct {\n\thandler Handler\n\tnext    *middleware\n}\n\nfunc (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {\n\tm.handler.ServeHTTP(rw, r, m.next.ServeHTTP)\n}\n\n// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni\n// middleware. The next http.HandlerFunc is automatically called after the Handler\n// is executed.\nfunc Wrap(handler http.Handler) Handler {\n\treturn HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\t\thandler.ServeHTTP(rw, r)\n\t\tnext(rw, r)\n\t})\n}\n\n// WrapFunc converts a http.HandlerFunc into a negroni.Handler so it can be used as a Negroni\n// middleware. The next http.HandlerFunc is automatically called after the Handler\n// is executed.\nfunc WrapFunc(handlerFunc http.HandlerFunc) Handler {\n\treturn HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\t\thandlerFunc(rw, r)\n\t\tnext(rw, r)\n\t})\n}\n\n// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler.\n// Negroni middleware is evaluated in the order that they are added to the stack using\n// the Use and UseHandler methods.\ntype Negroni struct {\n\tmiddleware middleware\n\thandlers   []Handler\n}\n\n// New returns a new Negroni instance with no middleware preconfigured.\nfunc New(handlers ...Handler) *Negroni {\n\treturn &Negroni{\n\t\thandlers:   handlers,\n\t\tmiddleware: build(handlers),\n\t}\n}\n\n// With returns a new Negroni instance that is a combination of the negroni\n// receiver's handlers and the provided handlers.\nfunc (n *Negroni) With(handlers ...Handler) *Negroni {\n\treturn New(\n\t\tappend(n.handlers, handlers...)...,\n\t)\n}\n\n// Classic returns a new Negroni instance with the default middleware already\n// in the stack.\n//\n// Recovery - Panic Recovery Middleware\n// Logger - Request/Response Logging\n// Static - Static File Serving\nfunc Classic() *Negroni {\n\treturn New(NewRecovery(), NewLogger(), NewStatic(http.Dir(\"public\")))\n}\n\nfunc (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {\n\tn.middleware.ServeHTTP(NewResponseWriter(rw), r)\n}\n\n// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.\nfunc (n *Negroni) Use(handler Handler) {\n\tif handler == nil {\n\t\tpanic(\"handler cannot be nil\")\n\t}\n\n\tn.handlers = append(n.handlers, handler)\n\tn.middleware = build(n.handlers)\n}\n\n// UseFunc adds a Negroni-style handler function onto the middleware stack.\nfunc (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {\n\tn.Use(HandlerFunc(handlerFunc))\n}\n\n// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.\nfunc (n *Negroni) UseHandler(handler http.Handler) {\n\tn.Use(Wrap(handler))\n}\n\n// UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack.\nfunc (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) {\n\tn.UseHandler(http.HandlerFunc(handlerFunc))\n}\n\n// Run is a convenience function that runs the negroni stack as an HTTP\n// server. The addr string, if provided, takes the same format as http.ListenAndServe.\n// If no address is provided but the PORT environment variable is set, the PORT value is used.\n// If neither is provided, the address' value will equal the DefaultAddress constant.\nfunc (n *Negroni) Run(addr ...string) {\n\tl := log.New(os.Stdout, \"[negroni] \", 0)\n\tfinalAddr := detectAddress(addr...)\n\tl.Printf(\"listening on %s\", finalAddr)\n\tl.Fatal(http.ListenAndServe(finalAddr, n))\n}\n\nfunc detectAddress(addr ...string) string {\n\tif len(addr) > 0 {\n\t\treturn addr[0]\n\t}\n\tif port := os.Getenv(\"PORT\"); port != \"\" {\n\t\treturn \":\" + port\n\t}\n\treturn DefaultAddress\n}\n\n// Returns a list of all the handlers in the current Negroni middleware chain.\nfunc (n *Negroni) Handlers() []Handler {\n\treturn n.handlers\n}\n\nfunc build(handlers []Handler) middleware {\n\tvar next middleware\n\n\tif len(handlers) == 0 {\n\t\treturn voidMiddleware()\n\t} else if len(handlers) > 1 {\n\t\tnext = build(handlers[1:])\n\t} else {\n\t\tnext = voidMiddleware()\n\t}\n\n\treturn middleware{handlers[0], &next}\n}\n\nfunc voidMiddleware() middleware {\n\treturn middleware{\n\t\tHandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),\n\t\t&middleware{},\n\t}\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/recovery.go",
    "content": "package negroni\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"text/template\"\n)\n\nconst (\n\tpanicText = \"PANIC: %s\\n%s\"\n\tpanicHTML = `<html>\n<head><title>PANIC: {{.RecoveredPanic}}</title></head>\n<style type=\"text/css\">\nhtml, body {\n\tfont-family: Helvetica, Arial, Sans;\n\tcolor: #333333;\n\tbackground-color: #ffffff;\n\tmargin: 0px;\n}\nh1 {\n\tcolor: #ffffff;\n\tbackground-color: #f14c4c;\n\tpadding: 20px;\n\tborder-bottom: 1px solid #2b3848;\n}\n.block {\n\tmargin: 2em;\n}\n.panic-interface {\n}\n\n.panic-stack-raw pre {\n\tpadding: 1em;\n\tbackground: #f6f8fa;\n\tborder: dashed 1px;\n}\n.panic-interface-title {\n\tfont-weight: bold;\n}\n</style>\n<body>\n<h1>Negroni - PANIC</h1>\n\n<div class=\"panic-interface block\">\n\t<h3>{{.RequestDescription}}</h3>\n\t<span class=\"panic-interface-title\">Runtime error:</span> <span class=\"panic-interface-element\">{{.RecoveredPanic}}</span>\n</div>\n\n{{ if .Stack }}\n<div class=\"panic-stack-raw block\">\n\t<h3>Runtime Stack</h3>\n\t<pre>{{.StackAsString}}</pre>\n</div>\n{{ end }}\n\n</body>\n</html>`\n\tnilRequestMessage = \"Request is nil\"\n)\n\nvar panicHTMLTemplate = template.Must(template.New(\"PanicPage\").Parse(panicHTML))\n\n// PanicInformation contains all\n// elements for printing stack informations.\ntype PanicInformation struct {\n\tRecoveredPanic interface{}\n\tStack          []byte\n\tRequest        *http.Request\n}\n\n// StackAsString returns a printable version of the stack\nfunc (p *PanicInformation) StackAsString() string {\n\treturn string(p.Stack)\n}\n\n// RequestDescription returns a printable description of the url\nfunc (p *PanicInformation) RequestDescription() string {\n\n\tif p.Request == nil {\n\t\treturn nilRequestMessage\n\t}\n\n\tvar queryOutput string\n\tif p.Request.URL.RawQuery != \"\" {\n\t\tqueryOutput = \"?\" + p.Request.URL.RawQuery\n\t}\n\treturn fmt.Sprintf(\"%s %s%s\", p.Request.Method, p.Request.URL.Path, queryOutput)\n}\n\n// PanicFormatter is an interface on object can implement\n// to be able to output the stack trace\ntype PanicFormatter interface {\n\t// FormatPanicError output the stack for a given answer/response.\n\t// In case the the middleware should not output the stack trace,\n\t// the field `Stack` of the passed `PanicInformation` instance equals `[]byte{}`.\n\tFormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation)\n}\n\n// TextPanicFormatter output the stack\n// as simple text on os.Stdout. If no `Content-Type` is set,\n// it will output the data as `text/plain; charset=utf-8`.\n// Otherwise, the origin `Content-Type` is kept.\ntype TextPanicFormatter struct{}\n\nfunc (t *TextPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) {\n\tif rw.Header().Get(\"Content-Type\") == \"\" {\n\t\trw.Header().Set(\"Content-Type\", \"text/plain; charset=utf-8\")\n\t}\n\tfmt.Fprintf(rw, panicText, infos.RecoveredPanic, infos.Stack)\n}\n\n// HTMLPanicFormatter output the stack inside\n// an HTML page. This has been largely inspired by\n// https://github.com/go-martini/martini/pull/156/commits.\ntype HTMLPanicFormatter struct{}\n\nfunc (t *HTMLPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) {\n\tif rw.Header().Get(\"Content-Type\") == \"\" {\n\t\trw.Header().Set(\"Content-Type\", \"text/html; charset=utf-8\")\n\t}\n\tpanicHTMLTemplate.Execute(rw, infos)\n}\n\n// Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one.\ntype Recovery struct {\n\tLogger           ALogger\n\tPrintStack       bool\n\tPanicHandlerFunc func(*PanicInformation)\n\tStackAll         bool\n\tStackSize        int\n\tFormatter        PanicFormatter\n\n\t// Deprecated: Use PanicHandlerFunc instead to receive panic\n\t// error with additional information (see PanicInformation)\n\tErrorHandlerFunc func(interface{})\n}\n\n// NewRecovery returns a new instance of Recovery\nfunc NewRecovery() *Recovery {\n\treturn &Recovery{\n\t\tLogger:     log.New(os.Stdout, \"[negroni] \", 0),\n\t\tPrintStack: true,\n\t\tStackAll:   false,\n\t\tStackSize:  1024 * 8,\n\t\tFormatter:  &TextPanicFormatter{},\n\t}\n}\n\nfunc (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\trw.WriteHeader(http.StatusInternalServerError)\n\n\t\t\tstack := make([]byte, rec.StackSize)\n\t\t\tstack = stack[:runtime.Stack(stack, rec.StackAll)]\n\t\t\tinfos := &PanicInformation{RecoveredPanic: err, Request: r}\n\n\t\t\tif rec.PrintStack {\n\t\t\t\tinfos.Stack = stack\n\t\t\t}\n\t\t\trec.Logger.Printf(panicText, err, stack)\n\t\t\trec.Formatter.FormatPanicError(rw, r, infos)\n\n\t\t\tif rec.ErrorHandlerFunc != nil {\n\t\t\t\tfunc() {\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tif err := recover(); err != nil {\n\t\t\t\t\t\t\trec.Logger.Printf(\"provided ErrorHandlerFunc panic'd: %s, trace:\\n%s\", err, debug.Stack())\n\t\t\t\t\t\t\trec.Logger.Printf(\"%s\\n\", debug.Stack())\n\t\t\t\t\t\t}\n\t\t\t\t\t}()\n\t\t\t\t\trec.ErrorHandlerFunc(err)\n\t\t\t\t}()\n\t\t\t}\n\t\t\tif rec.PanicHandlerFunc != nil {\n\t\t\t\tfunc() {\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tif err := recover(); err != nil {\n\t\t\t\t\t\t\trec.Logger.Printf(\"provided PanicHandlerFunc panic'd: %s, trace:\\n%s\", err, debug.Stack())\n\t\t\t\t\t\t\trec.Logger.Printf(\"%s\\n\", debug.Stack())\n\t\t\t\t\t\t}\n\t\t\t\t\t}()\n\t\t\t\t\trec.PanicHandlerFunc(infos)\n\t\t\t\t}()\n\t\t\t}\n\t\t}\n\t}()\n\n\tnext(rw, r)\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/response_writer.go",
    "content": "package negroni\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about\n// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter\n// if the functionality calls for it.\ntype ResponseWriter interface {\n\thttp.ResponseWriter\n\thttp.Flusher\n\t// Status returns the status code of the response or 0 if the response has\n\t// not been written\n\tStatus() int\n\t// Written returns whether or not the ResponseWriter has been written.\n\tWritten() bool\n\t// Size returns the size of the response body.\n\tSize() int\n\t// Before allows for a function to be called before the ResponseWriter has been written to. This is\n\t// useful for setting headers or any other operations that must happen before a response has been written.\n\tBefore(func(ResponseWriter))\n}\n\ntype beforeFunc func(ResponseWriter)\n\n// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter\nfunc NewResponseWriter(rw http.ResponseWriter) ResponseWriter {\n\tnrw := &responseWriter{\n\t\tResponseWriter: rw,\n\t}\n\n\tif _, ok := rw.(http.CloseNotifier); ok {\n\t\treturn &responseWriterCloseNotifer{nrw}\n\t}\n\n\treturn nrw\n}\n\ntype responseWriter struct {\n\thttp.ResponseWriter\n\tstatus      int\n\tsize        int\n\tbeforeFuncs []beforeFunc\n}\n\nfunc (rw *responseWriter) WriteHeader(s int) {\n\trw.status = s\n\trw.callBefore()\n\trw.ResponseWriter.WriteHeader(s)\n}\n\nfunc (rw *responseWriter) Write(b []byte) (int, error) {\n\tif !rw.Written() {\n\t\t// The status will be StatusOK if WriteHeader has not been called yet\n\t\trw.WriteHeader(http.StatusOK)\n\t}\n\tsize, err := rw.ResponseWriter.Write(b)\n\trw.size += size\n\treturn size, err\n}\n\nfunc (rw *responseWriter) Status() int {\n\treturn rw.status\n}\n\nfunc (rw *responseWriter) Size() int {\n\treturn rw.size\n}\n\nfunc (rw *responseWriter) Written() bool {\n\treturn rw.status != 0\n}\n\nfunc (rw *responseWriter) Before(before func(ResponseWriter)) {\n\trw.beforeFuncs = append(rw.beforeFuncs, before)\n}\n\nfunc (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {\n\thijacker, ok := rw.ResponseWriter.(http.Hijacker)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"the ResponseWriter doesn't support the Hijacker interface\")\n\t}\n\treturn hijacker.Hijack()\n}\n\nfunc (rw *responseWriter) callBefore() {\n\tfor i := len(rw.beforeFuncs) - 1; i >= 0; i-- {\n\t\trw.beforeFuncs[i](rw)\n\t}\n}\n\nfunc (rw *responseWriter) Flush() {\n\tflusher, ok := rw.ResponseWriter.(http.Flusher)\n\tif ok {\n\t\tif !rw.Written() {\n\t\t\t// The status will be StatusOK if WriteHeader has not been called yet\n\t\t\trw.WriteHeader(http.StatusOK)\n\t\t}\n\t\tflusher.Flush()\n\t}\n}\n\ntype responseWriterCloseNotifer struct {\n\t*responseWriter\n}\n\nfunc (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool {\n\treturn rw.ResponseWriter.(http.CloseNotifier).CloseNotify()\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/response_writer_pusher.go",
    "content": "//go:build go1.8\n// +build go1.8\n\npackage negroni\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc (rw *responseWriter) Push(target string, opts *http.PushOptions) error {\n\tpusher, ok := rw.ResponseWriter.(http.Pusher)\n\tif ok {\n\t\treturn pusher.Push(target, opts)\n\t}\n\treturn fmt.Errorf(\"the ResponseWriter doesn't support the Pusher interface\")\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/codegangsta/negroni/static.go",
    "content": "package negroni\n\nimport (\n\t\"net/http\"\n\t\"path\"\n\t\"strings\"\n)\n\n// Static is a middleware handler that serves static files in the given\n// directory/filesystem. If the file does not exist on the filesystem, it\n// passes along to the next middleware in the chain. If you desire \"fileserver\"\n// type behavior where it returns a 404 for unfound files, you should consider\n// using http.FileServer from the Go stdlib.\ntype Static struct {\n\t// Dir is the directory to serve static files from\n\tDir http.FileSystem\n\t// Prefix is the optional prefix used to serve the static directory content\n\tPrefix string\n\t// IndexFile defines which file to serve as index if it exists.\n\tIndexFile string\n}\n\n// NewStatic returns a new instance of Static\nfunc NewStatic(directory http.FileSystem) *Static {\n\treturn &Static{\n\t\tDir:       directory,\n\t\tPrefix:    \"\",\n\t\tIndexFile: \"index.html\",\n\t}\n}\n\nfunc (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\tif r.Method != \"GET\" && r.Method != \"HEAD\" {\n\t\tnext(rw, r)\n\t\treturn\n\t}\n\tfile := r.URL.Path\n\t// if we have a prefix, filter requests by stripping the prefix\n\tif s.Prefix != \"\" {\n\t\tif !strings.HasPrefix(file, s.Prefix) {\n\t\t\tnext(rw, r)\n\t\t\treturn\n\t\t}\n\t\tfile = file[len(s.Prefix):]\n\t\tif file != \"\" && file[0] != '/' {\n\t\t\tnext(rw, r)\n\t\t\treturn\n\t\t}\n\t}\n\tf, err := s.Dir.Open(file)\n\tif err != nil {\n\t\t// discard the error?\n\t\tnext(rw, r)\n\t\treturn\n\t}\n\tdefer f.Close()\n\n\tfi, err := f.Stat()\n\tif err != nil {\n\t\tnext(rw, r)\n\t\treturn\n\t}\n\n\t// try to serve index file\n\tif fi.IsDir() {\n\t\t// redirect if missing trailing slash\n\t\tif !strings.HasSuffix(r.URL.Path, \"/\") {\n\t\t\thttp.Redirect(rw, r, r.URL.Path+\"/\", http.StatusFound)\n\t\t\treturn\n\t\t}\n\n\t\tfile = path.Join(file, s.IndexFile)\n\t\tf, err = s.Dir.Open(file)\n\t\tif err != nil {\n\t\t\tnext(rw, r)\n\t\t\treturn\n\t\t}\n\t\tdefer f.Close()\n\n\t\tfi, err = f.Stat()\n\t\tif err != nil || fi.IsDir() {\n\t\t\tnext(rw, r)\n\t\t\treturn\n\t\t}\n\t}\n\n\thttp.ServeContent(rw, r, file, fi.ModTime(), f)\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/LICENSE",
    "content": "\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"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/commandinfo.go",
    "content": "// Copyright 2014 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"strings\"\n)\n\nconst (\n\tconnectionWatchState = 1 << iota\n\tconnectionMultiState\n\tconnectionSubscribeState\n\tconnectionMonitorState\n)\n\ntype commandInfo struct {\n\t// Set or Clear these states on connection.\n\tSet, Clear int\n}\n\nvar commandInfos = map[string]commandInfo{\n\t\"WATCH\":      {Set: connectionWatchState},\n\t\"UNWATCH\":    {Clear: connectionWatchState},\n\t\"MULTI\":      {Set: connectionMultiState},\n\t\"EXEC\":       {Clear: connectionWatchState | connectionMultiState},\n\t\"DISCARD\":    {Clear: connectionWatchState | connectionMultiState},\n\t\"PSUBSCRIBE\": {Set: connectionSubscribeState},\n\t\"SUBSCRIBE\":  {Set: connectionSubscribeState},\n\t\"MONITOR\":    {Set: connectionMonitorState},\n}\n\nfunc init() {\n\tfor n, ci := range commandInfos {\n\t\tcommandInfos[strings.ToLower(n)] = ci\n\t}\n}\n\nfunc lookupCommandInfo(commandName string) commandInfo {\n\tif ci, ok := commandInfos[commandName]; ok {\n\t\treturn ci\n\t}\n\treturn commandInfos[strings.ToUpper(commandName)]\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/conn.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar (\n\t_ ConnWithTimeout = (*conn)(nil)\n)\n\n// conn is the low-level implementation of Conn\ntype conn struct {\n\t// Shared\n\tmu      sync.Mutex\n\tpending int\n\terr     error\n\tconn    net.Conn\n\n\t// Read\n\treadTimeout time.Duration\n\tbr          *bufio.Reader\n\n\t// Write\n\twriteTimeout time.Duration\n\tbw           *bufio.Writer\n\n\t// Scratch space for formatting argument length.\n\t// '*' or '$', length, \"\\r\\n\"\n\tlenScratch [32]byte\n\n\t// Scratch space for formatting integers and floats.\n\tnumScratch [40]byte\n}\n\n// DialTimeout acts like Dial but takes timeouts for establishing the\n// connection to the server, writing a command and reading a reply.\n//\n// Deprecated: Use Dial with options instead.\nfunc DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) {\n\treturn Dial(network, address,\n\t\tDialConnectTimeout(connectTimeout),\n\t\tDialReadTimeout(readTimeout),\n\t\tDialWriteTimeout(writeTimeout))\n}\n\n// DialOption specifies an option for dialing a Redis server.\ntype DialOption struct {\n\tf func(*dialOptions)\n}\n\ntype dialOptions struct {\n\treadTimeout         time.Duration\n\twriteTimeout        time.Duration\n\ttlsHandshakeTimeout time.Duration\n\tdialer              *net.Dialer\n\tdialContext         func(ctx context.Context, network, addr string) (net.Conn, error)\n\tdb                  int\n\tusername            string\n\tpassword            string\n\tclientName          string\n\tuseTLS              bool\n\tskipVerify          bool\n\ttlsConfig           *tls.Config\n}\n\n// DialTLSHandshakeTimeout specifies the maximum amount of time waiting to\n// wait for a TLS handshake. Zero means no timeout.\n// If no DialTLSHandshakeTimeout option is specified then the default is 30 seconds.\nfunc DialTLSHandshakeTimeout(d time.Duration) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.tlsHandshakeTimeout = d\n\t}}\n}\n\n// DialReadTimeout specifies the timeout for reading a single command reply.\nfunc DialReadTimeout(d time.Duration) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.readTimeout = d\n\t}}\n}\n\n// DialWriteTimeout specifies the timeout for writing a single command.\nfunc DialWriteTimeout(d time.Duration) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.writeTimeout = d\n\t}}\n}\n\n// DialConnectTimeout specifies the timeout for connecting to the Redis server when\n// no DialNetDial option is specified.\n// If no DialConnectTimeout option is specified then the default is 30 seconds.\nfunc DialConnectTimeout(d time.Duration) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.dialer.Timeout = d\n\t}}\n}\n\n// DialKeepAlive specifies the keep-alive period for TCP connections to the Redis server\n// when no DialNetDial option is specified.\n// If zero, keep-alives are not enabled. If no DialKeepAlive option is specified then\n// the default of 5 minutes is used to ensure that half-closed TCP sessions are detected.\nfunc DialKeepAlive(d time.Duration) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.dialer.KeepAlive = d\n\t}}\n}\n\n// DialNetDial specifies a custom dial function for creating TCP\n// connections, otherwise a net.Dialer customized via the other options is used.\n// DialNetDial overrides DialConnectTimeout and DialKeepAlive.\nfunc DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.dialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {\n\t\t\treturn dial(network, addr)\n\t\t}\n\t}}\n}\n\n// DialContextFunc specifies a custom dial function with context for creating TCP\n// connections, otherwise a net.Dialer customized via the other options is used.\n// DialContextFunc overrides DialConnectTimeout and DialKeepAlive.\nfunc DialContextFunc(f func(ctx context.Context, network, addr string) (net.Conn, error)) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.dialContext = f\n\t}}\n}\n\n// DialDatabase specifies the database to select when dialing a connection.\nfunc DialDatabase(db int) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.db = db\n\t}}\n}\n\n// DialPassword specifies the password to use when connecting to\n// the Redis server.\nfunc DialPassword(password string) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.password = password\n\t}}\n}\n\n// DialUsername specifies the username to use when connecting to\n// the Redis server when Redis ACLs are used.\n// A DialPassword must also be passed otherwise this option will have no effect.\nfunc DialUsername(username string) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.username = username\n\t}}\n}\n\n// DialClientName specifies a client name to be used\n// by the Redis server connection.\nfunc DialClientName(name string) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.clientName = name\n\t}}\n}\n\n// DialTLSConfig specifies the config to use when a TLS connection is dialed.\n// Has no effect when not dialing a TLS connection.\nfunc DialTLSConfig(c *tls.Config) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.tlsConfig = c\n\t}}\n}\n\n// DialTLSSkipVerify disables server name verification when connecting over\n// TLS. Has no effect when not dialing a TLS connection.\nfunc DialTLSSkipVerify(skip bool) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.skipVerify = skip\n\t}}\n}\n\n// DialUseTLS specifies whether TLS should be used when connecting to the\n// server. This option is ignore by DialURL.\nfunc DialUseTLS(useTLS bool) DialOption {\n\treturn DialOption{func(do *dialOptions) {\n\t\tdo.useTLS = useTLS\n\t}}\n}\n\n// Dial connects to the Redis server at the given network and\n// address using the specified options.\nfunc Dial(network, address string, options ...DialOption) (Conn, error) {\n\treturn DialContext(context.Background(), network, address, options...)\n}\n\ntype tlsHandshakeTimeoutError struct{}\n\nfunc (tlsHandshakeTimeoutError) Timeout() bool   { return true }\nfunc (tlsHandshakeTimeoutError) Temporary() bool { return true }\nfunc (tlsHandshakeTimeoutError) Error() string   { return \"TLS handshake timeout\" }\n\n// DialContext connects to the Redis server at the given network and\n// address using the specified options and context.\nfunc DialContext(ctx context.Context, network, address string, options ...DialOption) (Conn, error) {\n\tdo := dialOptions{\n\t\tdialer: &net.Dialer{\n\t\t\tTimeout:   time.Second * 30,\n\t\t\tKeepAlive: time.Minute * 5,\n\t\t},\n\t\ttlsHandshakeTimeout: time.Second * 10,\n\t}\n\tfor _, option := range options {\n\t\toption.f(&do)\n\t}\n\tif do.dialContext == nil {\n\t\tdo.dialContext = do.dialer.DialContext\n\t}\n\n\tnetConn, err := do.dialContext(ctx, network, address)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif do.useTLS {\n\t\tvar tlsConfig *tls.Config\n\t\tif do.tlsConfig == nil {\n\t\t\ttlsConfig = &tls.Config{InsecureSkipVerify: do.skipVerify}\n\t\t} else {\n\t\t\ttlsConfig = do.tlsConfig.Clone()\n\t\t}\n\t\tif tlsConfig.ServerName == \"\" {\n\t\t\thost, _, err := net.SplitHostPort(address)\n\t\t\tif err != nil {\n\t\t\t\tnetConn.Close()\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ttlsConfig.ServerName = host\n\t\t}\n\n\t\ttlsConn := tls.Client(netConn, tlsConfig)\n\t\terrc := make(chan error, 2) // buffered so we don't block timeout or Handshake\n\t\tif d := do.tlsHandshakeTimeout; d != 0 {\n\t\t\ttimer := time.AfterFunc(d, func() {\n\t\t\t\terrc <- tlsHandshakeTimeoutError{}\n\t\t\t})\n\t\t\tdefer timer.Stop()\n\t\t}\n\t\tgo func() {\n\t\t\terrc <- tlsConn.Handshake()\n\t\t}()\n\t\tif err := <-errc; err != nil {\n\t\t\t// Timeout or Handshake error.\n\t\t\tnetConn.Close() // nolint: errcheck\n\t\t\treturn nil, err\n\t\t}\n\n\t\tnetConn = tlsConn\n\t}\n\n\tc := &conn{\n\t\tconn:         netConn,\n\t\tbw:           bufio.NewWriter(netConn),\n\t\tbr:           bufio.NewReader(netConn),\n\t\treadTimeout:  do.readTimeout,\n\t\twriteTimeout: do.writeTimeout,\n\t}\n\n\tif do.password != \"\" {\n\t\tauthArgs := make([]interface{}, 0, 2)\n\t\tif do.username != \"\" {\n\t\t\tauthArgs = append(authArgs, do.username)\n\t\t}\n\t\tauthArgs = append(authArgs, do.password)\n\t\tif _, err := c.DoContext(ctx, \"AUTH\", authArgs...); err != nil {\n\t\t\tnetConn.Close()\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif do.clientName != \"\" {\n\t\tif _, err := c.DoContext(ctx, \"CLIENT\", \"SETNAME\", do.clientName); err != nil {\n\t\t\tnetConn.Close()\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif do.db != 0 {\n\t\tif _, err := c.DoContext(ctx, \"SELECT\", do.db); err != nil {\n\t\t\tnetConn.Close()\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn c, nil\n}\n\nvar pathDBRegexp = regexp.MustCompile(`/(\\d*)\\z`)\n\n// DialURL wraps DialURLContext using context.Background.\nfunc DialURL(rawurl string, options ...DialOption) (Conn, error) {\n\tctx := context.Background()\n\n\treturn DialURLContext(ctx, rawurl, options...)\n}\n\n// DialURLContext connects to a Redis server at the given URL using the Redis\n// URI scheme. URLs should follow the draft IANA specification for the\n// scheme (https://www.iana.org/assignments/uri-schemes/prov/redis).\nfunc DialURLContext(ctx context.Context, rawurl string, options ...DialOption) (Conn, error) {\n\tu, err := url.Parse(rawurl)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif u.Scheme != \"redis\" && u.Scheme != \"rediss\" {\n\t\treturn nil, fmt.Errorf(\"invalid redis URL scheme: %s\", u.Scheme)\n\t}\n\n\tif u.Opaque != \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid redis URL, url is opaque: %s\", rawurl)\n\t}\n\n\t// As per the IANA draft spec, the host defaults to localhost and\n\t// the port defaults to 6379.\n\thost, port, err := net.SplitHostPort(u.Host)\n\tif err != nil {\n\t\t// assume port is missing\n\t\thost = u.Host\n\t\tport = \"6379\"\n\t}\n\tif host == \"\" {\n\t\thost = \"localhost\"\n\t}\n\taddress := net.JoinHostPort(host, port)\n\n\tif u.User != nil {\n\t\tpassword, isSet := u.User.Password()\n\t\tusername := u.User.Username()\n\t\tif isSet {\n\t\t\tif username != \"\" {\n\t\t\t\t// ACL\n\t\t\t\toptions = append(options, DialUsername(username), DialPassword(password))\n\t\t\t} else {\n\t\t\t\t// requirepass - user-info username:password with blank username\n\t\t\t\toptions = append(options, DialPassword(password))\n\t\t\t}\n\t\t} else if username != \"\" {\n\t\t\t// requirepass - redis-cli compatibility which treats as single arg in user-info as a password\n\t\t\toptions = append(options, DialPassword(username))\n\t\t}\n\t}\n\n\tmatch := pathDBRegexp.FindStringSubmatch(u.Path)\n\tif len(match) == 2 {\n\t\tdb := 0\n\t\tif len(match[1]) > 0 {\n\t\t\tdb, err = strconv.Atoi(match[1])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid database: %s\", u.Path[1:])\n\t\t\t}\n\t\t}\n\t\tif db != 0 {\n\t\t\toptions = append(options, DialDatabase(db))\n\t\t}\n\t} else if u.Path != \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid database: %s\", u.Path[1:])\n\t}\n\n\toptions = append(options, DialUseTLS(u.Scheme == \"rediss\"))\n\n\treturn DialContext(ctx, \"tcp\", address, options...)\n}\n\n// NewConn returns a new Redigo connection for the given net connection.\nfunc NewConn(netConn net.Conn, readTimeout, writeTimeout time.Duration) Conn {\n\treturn &conn{\n\t\tconn:         netConn,\n\t\tbw:           bufio.NewWriter(netConn),\n\t\tbr:           bufio.NewReader(netConn),\n\t\treadTimeout:  readTimeout,\n\t\twriteTimeout: writeTimeout,\n\t}\n}\n\nfunc (c *conn) Close() error {\n\tc.mu.Lock()\n\terr := c.err\n\tif c.err == nil {\n\t\tc.err = errors.New(\"redigo: closed\")\n\t\terr = c.conn.Close()\n\t}\n\tc.mu.Unlock()\n\treturn err\n}\n\nfunc (c *conn) fatal(err error) error {\n\tc.mu.Lock()\n\tif c.err == nil {\n\t\tc.err = err\n\t\t// Close connection to force errors on subsequent calls and to unblock\n\t\t// other reader or writer.\n\t\tc.conn.Close()\n\t}\n\tc.mu.Unlock()\n\treturn err\n}\n\nfunc (c *conn) Err() error {\n\tc.mu.Lock()\n\terr := c.err\n\tc.mu.Unlock()\n\treturn err\n}\n\nfunc (c *conn) writeLen(prefix byte, n int) error {\n\tc.lenScratch[len(c.lenScratch)-1] = '\\n'\n\tc.lenScratch[len(c.lenScratch)-2] = '\\r'\n\ti := len(c.lenScratch) - 3\n\tfor {\n\t\tc.lenScratch[i] = byte('0' + n%10)\n\t\ti -= 1\n\t\tn = n / 10\n\t\tif n == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\tc.lenScratch[i] = prefix\n\t_, err := c.bw.Write(c.lenScratch[i:])\n\treturn err\n}\n\nfunc (c *conn) writeString(s string) error {\n\tif err := c.writeLen('$', len(s)); err != nil {\n\t\treturn err\n\t}\n\tif _, err := c.bw.WriteString(s); err != nil {\n\t\treturn err\n\t}\n\t_, err := c.bw.WriteString(\"\\r\\n\")\n\treturn err\n}\n\nfunc (c *conn) writeBytes(p []byte) error {\n\tif err := c.writeLen('$', len(p)); err != nil {\n\t\treturn err\n\t}\n\tif _, err := c.bw.Write(p); err != nil {\n\t\treturn err\n\t}\n\t_, err := c.bw.WriteString(\"\\r\\n\")\n\treturn err\n}\n\nfunc (c *conn) writeInt64(n int64) error {\n\treturn c.writeBytes(strconv.AppendInt(c.numScratch[:0], n, 10))\n}\n\nfunc (c *conn) writeFloat64(n float64) error {\n\treturn c.writeBytes(strconv.AppendFloat(c.numScratch[:0], n, 'g', -1, 64))\n}\n\nfunc (c *conn) writeCommand(cmd string, args []interface{}) error {\n\tif err := c.writeLen('*', 1+len(args)); err != nil {\n\t\treturn err\n\t}\n\tif err := c.writeString(cmd); err != nil {\n\t\treturn err\n\t}\n\tfor _, arg := range args {\n\t\tif err := c.writeArg(arg, true); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (c *conn) writeArg(arg interface{}, argumentTypeOK bool) (err error) {\n\tswitch arg := arg.(type) {\n\tcase string:\n\t\treturn c.writeString(arg)\n\tcase []byte:\n\t\treturn c.writeBytes(arg)\n\tcase int:\n\t\treturn c.writeInt64(int64(arg))\n\tcase int64:\n\t\treturn c.writeInt64(arg)\n\tcase float64:\n\t\treturn c.writeFloat64(arg)\n\tcase bool:\n\t\tif arg {\n\t\t\treturn c.writeString(\"1\")\n\t\t} else {\n\t\t\treturn c.writeString(\"0\")\n\t\t}\n\tcase nil:\n\t\treturn c.writeString(\"\")\n\tcase Argument:\n\t\tif argumentTypeOK {\n\t\t\treturn c.writeArg(arg.RedisArg(), false)\n\t\t}\n\t\t// See comment in default clause below.\n\t\tvar buf bytes.Buffer\n\t\tfmt.Fprint(&buf, arg)\n\t\treturn c.writeBytes(buf.Bytes())\n\tdefault:\n\t\t// This default clause is intended to handle builtin numeric types.\n\t\t// The function should return an error for other types, but this is not\n\t\t// done for compatibility with previous versions of the package.\n\t\tvar buf bytes.Buffer\n\t\tfmt.Fprint(&buf, arg)\n\t\treturn c.writeBytes(buf.Bytes())\n\t}\n}\n\ntype protocolError string\n\nfunc (pe protocolError) Error() string {\n\treturn fmt.Sprintf(\"redigo: %s (possible server error or unsupported concurrent read by application)\", string(pe))\n}\n\n// readLine reads a line of input from the RESP stream.\nfunc (c *conn) readLine() ([]byte, error) {\n\t// To avoid allocations, attempt to read the line using ReadSlice. This\n\t// call typically succeeds. The known case where the call fails is when\n\t// reading the output from the MONITOR command.\n\tp, err := c.br.ReadSlice('\\n')\n\tif err == bufio.ErrBufferFull {\n\t\t// The line does not fit in the bufio.Reader's buffer. Fall back to\n\t\t// allocating a buffer for the line.\n\t\tbuf := append([]byte{}, p...)\n\t\tfor err == bufio.ErrBufferFull {\n\t\t\tp, err = c.br.ReadSlice('\\n')\n\t\t\tbuf = append(buf, p...)\n\t\t}\n\t\tp = buf\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ti := len(p) - 2\n\tif i < 0 || p[i] != '\\r' {\n\t\treturn nil, protocolError(\"bad response line terminator\")\n\t}\n\treturn p[:i], nil\n}\n\n// parseLen parses bulk string and array lengths.\nfunc parseLen(p []byte) (int, error) {\n\tif len(p) == 0 {\n\t\treturn -1, protocolError(\"malformed length\")\n\t}\n\n\tif p[0] == '-' && len(p) == 2 && p[1] == '1' {\n\t\t// handle $-1 and $-1 null replies.\n\t\treturn -1, nil\n\t}\n\n\tvar n int\n\tfor _, b := range p {\n\t\tn *= 10\n\t\tif b < '0' || b > '9' {\n\t\t\treturn -1, protocolError(\"illegal bytes in length\")\n\t\t}\n\t\tn += int(b - '0')\n\t}\n\n\treturn n, nil\n}\n\n// parseInt parses an integer reply.\nfunc parseInt(p []byte) (interface{}, error) {\n\tif len(p) == 0 {\n\t\treturn 0, protocolError(\"malformed integer\")\n\t}\n\n\tvar negate bool\n\tif p[0] == '-' {\n\t\tnegate = true\n\t\tp = p[1:]\n\t\tif len(p) == 0 {\n\t\t\treturn 0, protocolError(\"malformed integer\")\n\t\t}\n\t}\n\n\tvar n int64\n\tfor _, b := range p {\n\t\tn *= 10\n\t\tif b < '0' || b > '9' {\n\t\t\treturn 0, protocolError(\"illegal bytes in length\")\n\t\t}\n\t\tn += int64(b - '0')\n\t}\n\n\tif negate {\n\t\tn = -n\n\t}\n\treturn n, nil\n}\n\nvar (\n\tokReply   interface{} = \"OK\"\n\tpongReply interface{} = \"PONG\"\n)\n\nfunc (c *conn) readReply() (interface{}, error) {\n\tline, err := c.readLine()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(line) == 0 {\n\t\treturn nil, protocolError(\"short response line\")\n\t}\n\tswitch line[0] {\n\tcase '+':\n\t\tswitch string(line[1:]) {\n\t\tcase \"OK\":\n\t\t\t// Avoid allocation for frequent \"+OK\" response.\n\t\t\treturn okReply, nil\n\t\tcase \"PONG\":\n\t\t\t// Avoid allocation in PING command benchmarks :)\n\t\t\treturn pongReply, nil\n\t\tdefault:\n\t\t\treturn string(line[1:]), nil\n\t\t}\n\tcase '-':\n\t\treturn Error(line[1:]), nil\n\tcase ':':\n\t\treturn parseInt(line[1:])\n\tcase '$':\n\t\tn, err := parseLen(line[1:])\n\t\tif n < 0 || err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tp := make([]byte, n)\n\t\t_, err = io.ReadFull(c.br, p)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif line, err := c.readLine(); err != nil {\n\t\t\treturn nil, err\n\t\t} else if len(line) != 0 {\n\t\t\treturn nil, protocolError(\"bad bulk string format\")\n\t\t}\n\t\treturn p, nil\n\tcase '*':\n\t\tn, err := parseLen(line[1:])\n\t\tif n < 0 || err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tr := make([]interface{}, n)\n\t\tfor i := range r {\n\t\t\tr[i], err = c.readReply()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\treturn r, nil\n\t}\n\treturn nil, protocolError(\"unexpected response line\")\n}\n\nfunc (c *conn) Send(cmd string, args ...interface{}) error {\n\tc.mu.Lock()\n\tc.pending += 1\n\tc.mu.Unlock()\n\tif c.writeTimeout != 0 {\n\t\tif err := c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil {\n\t\t\treturn c.fatal(err)\n\t\t}\n\t}\n\tif err := c.writeCommand(cmd, args); err != nil {\n\t\treturn c.fatal(err)\n\t}\n\treturn nil\n}\n\nfunc (c *conn) Flush() error {\n\tif c.writeTimeout != 0 {\n\t\tif err := c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil {\n\t\t\treturn c.fatal(err)\n\t\t}\n\t}\n\tif err := c.bw.Flush(); err != nil {\n\t\treturn c.fatal(err)\n\t}\n\treturn nil\n}\n\nfunc (c *conn) Receive() (interface{}, error) {\n\treturn c.ReceiveWithTimeout(c.readTimeout)\n}\n\nfunc (c *conn) ReceiveContext(ctx context.Context) (interface{}, error) {\n\tvar realTimeout time.Duration\n\tif dl, ok := ctx.Deadline(); ok {\n\t\ttimeout := time.Until(dl)\n\t\tif timeout >= c.readTimeout && c.readTimeout != 0 {\n\t\t\trealTimeout = c.readTimeout\n\t\t} else if timeout <= 0 {\n\t\t\treturn nil, c.fatal(context.DeadlineExceeded)\n\t\t} else {\n\t\t\trealTimeout = timeout\n\t\t}\n\t} else {\n\t\trealTimeout = c.readTimeout\n\t}\n\tendch := make(chan struct{})\n\tvar r interface{}\n\tvar e error\n\tgo func() {\n\t\tdefer close(endch)\n\n\t\tr, e = c.ReceiveWithTimeout(realTimeout)\n\t}()\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, c.fatal(ctx.Err())\n\tcase <-endch:\n\t\treturn r, e\n\t}\n}\n\nfunc (c *conn) ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error) {\n\tvar deadline time.Time\n\tif timeout != 0 {\n\t\tdeadline = time.Now().Add(timeout)\n\t}\n\tif err := c.conn.SetReadDeadline(deadline); err != nil {\n\t\treturn nil, c.fatal(err)\n\t}\n\n\tif reply, err = c.readReply(); err != nil {\n\t\treturn nil, c.fatal(err)\n\t}\n\t// When using pub/sub, the number of receives can be greater than the\n\t// number of sends. To enable normal use of the connection after\n\t// unsubscribing from all channels, we do not decrement pending to a\n\t// negative value.\n\t//\n\t// The pending field is decremented after the reply is read to handle the\n\t// case where Receive is called before Send.\n\tc.mu.Lock()\n\tif c.pending > 0 {\n\t\tc.pending -= 1\n\t}\n\tc.mu.Unlock()\n\tif err, ok := reply.(Error); ok {\n\t\treturn nil, err\n\t}\n\treturn\n}\n\nfunc (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) {\n\treturn c.DoWithTimeout(c.readTimeout, cmd, args...)\n}\n\nfunc (c *conn) DoContext(ctx context.Context, cmd string, args ...interface{}) (interface{}, error) {\n\tvar realTimeout time.Duration\n\tif dl, ok := ctx.Deadline(); ok {\n\t\ttimeout := time.Until(dl)\n\t\tif timeout >= c.readTimeout && c.readTimeout != 0 {\n\t\t\trealTimeout = c.readTimeout\n\t\t} else if timeout <= 0 {\n\t\t\treturn nil, c.fatal(context.DeadlineExceeded)\n\t\t} else {\n\t\t\trealTimeout = timeout\n\t\t}\n\t} else {\n\t\trealTimeout = c.readTimeout\n\t}\n\tendch := make(chan struct{})\n\tvar r interface{}\n\tvar e error\n\tgo func() {\n\t\tdefer close(endch)\n\n\t\tr, e = c.DoWithTimeout(realTimeout, cmd, args...)\n\t}()\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, c.fatal(ctx.Err())\n\tcase <-endch:\n\t\treturn r, e\n\t}\n}\n\nfunc (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {\n\tc.mu.Lock()\n\tpending := c.pending\n\tc.pending = 0\n\tc.mu.Unlock()\n\n\tif cmd == \"\" && pending == 0 {\n\t\treturn nil, nil\n\t}\n\n\tif c.writeTimeout != 0 {\n\t\tif err := c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil {\n\t\t\treturn nil, c.fatal(err)\n\t\t}\n\t}\n\n\tif cmd != \"\" {\n\t\tif err := c.writeCommand(cmd, args); err != nil {\n\t\t\treturn nil, c.fatal(err)\n\t\t}\n\t}\n\n\tif err := c.bw.Flush(); err != nil {\n\t\treturn nil, c.fatal(err)\n\t}\n\n\tvar deadline time.Time\n\tif readTimeout != 0 {\n\t\tdeadline = time.Now().Add(readTimeout)\n\t}\n\tif err := c.conn.SetReadDeadline(deadline); err != nil {\n\t\treturn nil, c.fatal(err)\n\t}\n\n\tif cmd == \"\" {\n\t\treply := make([]interface{}, pending)\n\t\tfor i := range reply {\n\t\t\tr, e := c.readReply()\n\t\t\tif e != nil {\n\t\t\t\treturn nil, c.fatal(e)\n\t\t\t}\n\t\t\treply[i] = r\n\t\t}\n\t\treturn reply, nil\n\t}\n\n\tvar err error\n\tvar reply interface{}\n\tfor i := 0; i <= pending; i++ {\n\t\tvar e error\n\t\tif reply, e = c.readReply(); e != nil {\n\t\t\treturn nil, c.fatal(e)\n\t\t}\n\t\tif e, ok := reply.(Error); ok && err == nil {\n\t\t\terr = e\n\t\t}\n\t}\n\treturn reply, err\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/doc.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\n// Package redis is a client for the Redis database.\n//\n// The Redigo FAQ (https://github.com/gomodule/redigo/wiki/FAQ) contains more\n// documentation about this package.\n//\n// # Connections\n//\n// The Conn interface is the primary interface for working with Redis.\n// Applications create connections by calling the Dial, DialWithTimeout or\n// NewConn functions. In the future, functions will be added for creating\n// sharded and other types of connections.\n//\n// The application must call the connection Close method when the application\n// is done with the connection.\n//\n// # Executing Commands\n//\n// The Conn interface has a generic method for executing Redis commands:\n//\n//\tDo(commandName string, args ...interface{}) (reply interface{}, err error)\n//\n// The Redis command reference (http://redis.io/commands) lists the available\n// commands. An example of using the Redis APPEND command is:\n//\n//\tn, err := conn.Do(\"APPEND\", \"key\", \"value\")\n//\n// The Do method converts command arguments to bulk strings for transmission\n// to the server as follows:\n//\n//\tGo Type                 Conversion\n//\t[]byte                  Sent as is\n//\tstring                  Sent as is\n//\tint, int64              strconv.FormatInt(v)\n//\tfloat64                 strconv.FormatFloat(v, 'g', -1, 64)\n//\tbool                    true -> \"1\", false -> \"0\"\n//\tnil                     \"\"\n//\tall other types         fmt.Fprint(w, v)\n//\n// Redis command reply types are represented using the following Go types:\n//\n//\tRedis type              Go type\n//\terror                   redis.Error\n//\tinteger                 int64\n//\tsimple string           string\n//\tbulk string             []byte or nil if value not present.\n//\tarray                   []interface{} or nil if value not present.\n//\n// Use type assertions or the reply helper functions to convert from\n// interface{} to the specific Go type for the command result.\n//\n// # Pipelining\n//\n// Connections support pipelining using the Send, Flush and Receive methods.\n//\n//\tSend(commandName string, args ...interface{}) error\n//\tFlush() error\n//\tReceive() (reply interface{}, err error)\n//\n// Send writes the command to the connection's output buffer. Flush flushes the\n// connection's output buffer to the server. Receive reads a single reply from\n// the server. The following example shows a simple pipeline.\n//\n//\tc.Send(\"SET\", \"foo\", \"bar\")\n//\tc.Send(\"GET\", \"foo\")\n//\tc.Flush()\n//\tc.Receive() // reply from SET\n//\tv, err = c.Receive() // reply from GET\n//\n// The Do method combines the functionality of the Send, Flush and Receive\n// methods. The Do method starts by writing the command and flushing the output\n// buffer. Next, the Do method receives all pending replies including the reply\n// for the command just sent by Do. If any of the received replies is an error,\n// then Do returns the error. If there are no errors, then Do returns the last\n// reply. If the command argument to the Do method is \"\", then the Do method\n// will flush the output buffer and receive pending replies without sending a\n// command.\n//\n// Use the Send and Do methods to implement pipelined transactions.\n//\n//\tc.Send(\"MULTI\")\n//\tc.Send(\"INCR\", \"foo\")\n//\tc.Send(\"INCR\", \"bar\")\n//\tr, err := c.Do(\"EXEC\")\n//\tfmt.Println(r) // prints [1, 1]\n//\n// # Concurrency\n//\n// Connections support one concurrent caller to the Receive method and one\n// concurrent caller to the Send and Flush methods. No other concurrency is\n// supported including concurrent calls to the Do and Close methods.\n//\n// For full concurrent access to Redis, use the thread-safe Pool to get, use\n// and release a connection from within a goroutine. Connections returned from\n// a Pool have the concurrency restrictions described in the previous\n// paragraph.\n//\n// # Publish and Subscribe\n//\n// Use the Send, Flush and Receive methods to implement Pub/Sub subscribers.\n//\n//\tc.Send(\"SUBSCRIBE\", \"example\")\n//\tc.Flush()\n//\tfor {\n//\t    reply, err := c.Receive()\n//\t    if err != nil {\n//\t        return err\n//\t    }\n//\t    // process pushed message\n//\t}\n//\n// The PubSubConn type wraps a Conn with convenience methods for implementing\n// subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods\n// send and flush a subscription management command. The receive method\n// converts a pushed message to convenient types for use in a type switch.\n//\n//\tpsc := redis.PubSubConn{Conn: c}\n//\tpsc.Subscribe(\"example\")\n//\tfor {\n//\t    switch v := psc.Receive().(type) {\n//\t    case redis.Message:\n//\t        fmt.Printf(\"%s: message: %s\\n\", v.Channel, v.Data)\n//\t    case redis.Subscription:\n//\t        fmt.Printf(\"%s: %s %d\\n\", v.Channel, v.Kind, v.Count)\n//\t    case error:\n//\t        return v\n//\t    }\n//\t}\n//\n// # Reply Helpers\n//\n// The Bool, Int, Bytes, String, Strings and Values functions convert a reply\n// to a value of a specific type. To allow convenient wrapping of calls to the\n// connection Do and Receive methods, the functions take a second argument of\n// type error.  If the error is non-nil, then the helper function returns the\n// error. If the error is nil, the function converts the reply to the specified\n// type:\n//\n//\texists, err := redis.Bool(c.Do(\"EXISTS\", \"foo\"))\n//\tif err != nil {\n//\t    // handle error return from c.Do or type conversion error.\n//\t}\n//\n// The Scan function converts elements of a array reply to Go types:\n//\n//\tvar value1 int\n//\tvar value2 string\n//\treply, err := redis.Values(c.Do(\"MGET\", \"key1\", \"key2\"))\n//\tif err != nil {\n//\t    // handle error\n//\t}\n//\t if _, err := redis.Scan(reply, &value1, &value2); err != nil {\n//\t    // handle error\n//\t}\n//\n// # Errors\n//\n// Connection methods return error replies from the server as type redis.Error.\n//\n// Call the connection Err() method to determine if the connection encountered\n// non-recoverable error such as a network error or protocol parsing error. If\n// Err() returns a non-nil value, then the connection is not usable and should\n// be closed.\npackage redis\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/log.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n)\n\nvar (\n\t_ ConnWithTimeout = (*loggingConn)(nil)\n)\n\n// NewLoggingConn returns a logging wrapper around a connection.\nfunc NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn {\n\tif prefix != \"\" {\n\t\tprefix = prefix + \".\"\n\t}\n\treturn &loggingConn{conn, logger, prefix, nil}\n}\n\n// NewLoggingConnFilter returns a logging wrapper around a connection and a filter function.\nfunc NewLoggingConnFilter(conn Conn, logger *log.Logger, prefix string, skip func(cmdName string) bool) Conn {\n\tif prefix != \"\" {\n\t\tprefix = prefix + \".\"\n\t}\n\treturn &loggingConn{conn, logger, prefix, skip}\n}\n\ntype loggingConn struct {\n\tConn\n\tlogger *log.Logger\n\tprefix string\n\tskip   func(cmdName string) bool\n}\n\nfunc (c *loggingConn) Close() error {\n\terr := c.Conn.Close()\n\tvar buf bytes.Buffer\n\tfmt.Fprintf(&buf, \"%sClose() -> (%v)\", c.prefix, err)\n\tc.logger.Output(2, buf.String()) // nolint: errcheck\n\treturn err\n}\n\nfunc (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) {\n\tconst chop = 32\n\tswitch v := v.(type) {\n\tcase []byte:\n\t\tif len(v) > chop {\n\t\t\tfmt.Fprintf(buf, \"%q...\", v[:chop])\n\t\t} else {\n\t\t\tfmt.Fprintf(buf, \"%q\", v)\n\t\t}\n\tcase string:\n\t\tif len(v) > chop {\n\t\t\tfmt.Fprintf(buf, \"%q...\", v[:chop])\n\t\t} else {\n\t\t\tfmt.Fprintf(buf, \"%q\", v)\n\t\t}\n\tcase []interface{}:\n\t\tif len(v) == 0 {\n\t\t\tbuf.WriteString(\"[]\")\n\t\t} else {\n\t\t\tsep := \"[\"\n\t\t\tfin := \"]\"\n\t\t\tif len(v) > chop {\n\t\t\t\tv = v[:chop]\n\t\t\t\tfin = \"...]\"\n\t\t\t}\n\t\t\tfor _, vv := range v {\n\t\t\t\tbuf.WriteString(sep)\n\t\t\t\tc.printValue(buf, vv)\n\t\t\t\tsep = \", \"\n\t\t\t}\n\t\t\tbuf.WriteString(fin)\n\t\t}\n\tdefault:\n\t\tfmt.Fprint(buf, v)\n\t}\n}\n\nfunc (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) {\n\tif c.skip != nil && c.skip(commandName) {\n\t\treturn\n\t}\n\tvar buf bytes.Buffer\n\tfmt.Fprintf(&buf, \"%s%s(\", c.prefix, method)\n\tif method != \"Receive\" {\n\t\tbuf.WriteString(commandName)\n\t\tfor _, arg := range args {\n\t\t\tbuf.WriteString(\", \")\n\t\t\tc.printValue(&buf, arg)\n\t\t}\n\t}\n\tbuf.WriteString(\") -> (\")\n\tif method != \"Send\" {\n\t\tc.printValue(&buf, reply)\n\t\tbuf.WriteString(\", \")\n\t}\n\tfmt.Fprintf(&buf, \"%v)\", err)\n\tc.logger.Output(3, buf.String()) // nolint: errcheck\n}\n\nfunc (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) {\n\treply, err := c.Conn.Do(commandName, args...)\n\tc.print(\"Do\", commandName, args, reply, err)\n\treturn reply, err\n}\n\nfunc (c *loggingConn) DoContext(ctx context.Context, commandName string, args ...interface{}) (interface{}, error) {\n\treply, err := DoContext(c.Conn, ctx, commandName, args...)\n\tc.print(\"DoContext\", commandName, args, reply, err)\n\treturn reply, err\n}\n\nfunc (c *loggingConn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (interface{}, error) {\n\treply, err := DoWithTimeout(c.Conn, timeout, commandName, args...)\n\tc.print(\"DoWithTimeout\", commandName, args, reply, err)\n\treturn reply, err\n}\n\nfunc (c *loggingConn) Send(commandName string, args ...interface{}) error {\n\terr := c.Conn.Send(commandName, args...)\n\tc.print(\"Send\", commandName, args, nil, err)\n\treturn err\n}\n\nfunc (c *loggingConn) Receive() (interface{}, error) {\n\treply, err := c.Conn.Receive()\n\tc.print(\"Receive\", \"\", nil, reply, err)\n\treturn reply, err\n}\n\nfunc (c *loggingConn) ReceiveContext(ctx context.Context) (interface{}, error) {\n\treply, err := ReceiveContext(c.Conn, ctx)\n\tc.print(\"ReceiveContext\", \"\", nil, reply, err)\n\treturn reply, err\n}\n\nfunc (c *loggingConn) ReceiveWithTimeout(timeout time.Duration) (interface{}, error) {\n\treply, err := ReceiveWithTimeout(c.Conn, timeout)\n\tc.print(\"ReceiveWithTimeout\", \"\", nil, reply, err)\n\treturn reply, err\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/pool.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/rand\"\n\t\"crypto/sha1\"\n\t\"errors\"\n\t\"io\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar (\n\t_ ConnWithTimeout = (*activeConn)(nil)\n\t_ ConnWithTimeout = (*errorConn)(nil)\n)\n\nvar nowFunc = time.Now // for testing\n\n// ErrPoolExhausted is returned from a pool connection method (Do, Send,\n// Receive, Flush, Err) when the maximum number of database connections in the\n// pool has been reached.\nvar ErrPoolExhausted = errors.New(\"redigo: connection pool exhausted\")\n\nvar (\n\terrConnClosed = errors.New(\"redigo: connection closed\")\n)\n\n// Pool maintains a pool of connections. The application calls the Get method\n// to get a connection from the pool and the connection's Close method to\n// return the connection's resources to the pool.\n//\n// The following example shows how to use a pool in a web application. The\n// application creates a pool at application startup and makes it available to\n// request handlers using a package level variable. The pool configuration used\n// here is an example, not a recommendation.\n//\n//\tfunc newPool(addr string) *redis.Pool {\n//\t  return &redis.Pool{\n//\t    MaxIdle: 3,\n//\t    IdleTimeout: 240 * time.Second,\n//\t    // Dial or DialContext must be set. When both are set, DialContext takes precedence over Dial.\n//\t    Dial: func () (redis.Conn, error) { return redis.Dial(\"tcp\", addr) },\n//\t  }\n//\t}\n//\n//\tvar (\n//\t  pool *redis.Pool\n//\t  redisServer = flag.String(\"redisServer\", \":6379\", \"\")\n//\t)\n//\n//\tfunc main() {\n//\t  flag.Parse()\n//\t  pool = newPool(*redisServer)\n//\t  ...\n//\t}\n//\n// A request handler gets a connection from the pool and closes the connection\n// when the handler is done:\n//\n//\tfunc serveHome(w http.ResponseWriter, r *http.Request) {\n//\t    conn := pool.Get()\n//\t    defer conn.Close()\n//\t    ...\n//\t}\n//\n// Use the Dial function to authenticate connections with the AUTH command or\n// select a database with the SELECT command:\n//\n//\tpool := &redis.Pool{\n//\t  // Other pool configuration not shown in this example.\n//\t  Dial: func () (redis.Conn, error) {\n//\t    c, err := redis.Dial(\"tcp\", server)\n//\t    if err != nil {\n//\t      return nil, err\n//\t    }\n//\t    if _, err := c.Do(\"AUTH\", password); err != nil {\n//\t      c.Close()\n//\t      return nil, err\n//\t    }\n//\t    if _, err := c.Do(\"SELECT\", db); err != nil {\n//\t      c.Close()\n//\t      return nil, err\n//\t    }\n//\t    return c, nil\n//\t  },\n//\t}\n//\n// Use the TestOnBorrow function to check the health of an idle connection\n// before the connection is returned to the application. This example PINGs\n// connections that have been idle more than a minute:\n//\n//\tpool := &redis.Pool{\n//\t  // Other pool configuration not shown in this example.\n//\t  TestOnBorrow: func(c redis.Conn, t time.Time) error {\n//\t    if time.Since(t) < time.Minute {\n//\t      return nil\n//\t    }\n//\t    _, err := c.Do(\"PING\")\n//\t    return err\n//\t  },\n//\t}\ntype Pool struct {\n\t// Dial is an application supplied function for creating and configuring a\n\t// connection.\n\t//\n\t// The connection returned from Dial must not be in a special state\n\t// (subscribed to pubsub channel, transaction started, ...).\n\tDial func() (Conn, error)\n\n\t// DialContext is an application supplied function for creating and configuring a\n\t// connection with the given context.\n\t//\n\t// The connection returned from Dial must not be in a special state\n\t// (subscribed to pubsub channel, transaction started, ...).\n\tDialContext func(ctx context.Context) (Conn, error)\n\n\t// TestOnBorrow is an optional application supplied function for checking\n\t// the health of an idle connection before the connection is used again by\n\t// the application. Argument t is the time that the connection was returned\n\t// to the pool. If the function returns an error, then the connection is\n\t// closed.\n\tTestOnBorrow func(c Conn, t time.Time) error\n\n\t// Maximum number of idle connections in the pool.\n\tMaxIdle int\n\n\t// Maximum number of connections allocated by the pool at a given time.\n\t// When zero, there is no limit on the number of connections in the pool.\n\tMaxActive int\n\n\t// Close connections after remaining idle for this duration. If the value\n\t// is zero, then idle connections are not closed. Applications should set\n\t// the timeout to a value less than the server's timeout.\n\tIdleTimeout time.Duration\n\n\t// If Wait is true and the pool is at the MaxActive limit, then Get() waits\n\t// for a connection to be returned to the pool before returning.\n\tWait bool\n\n\t// Close connections older than this duration. If the value is zero, then\n\t// the pool does not close connections based on age.\n\tMaxConnLifetime time.Duration\n\n\tmu           sync.Mutex    // mu protects the following fields\n\tclosed       bool          // set to true when the pool is closed.\n\tactive       int           // the number of open connections in the pool\n\tinitOnce     sync.Once     // the init ch once func\n\tch           chan struct{} // limits open connections when p.Wait is true\n\tidle         idleList      // idle connections\n\twaitCount    int64         // total number of connections waited for.\n\twaitDuration time.Duration // total time waited for new connections.\n}\n\n// NewPool creates a new pool.\n//\n// Deprecated: Initialize the Pool directly as shown in the example.\nfunc NewPool(newFn func() (Conn, error), maxIdle int) *Pool {\n\treturn &Pool{Dial: newFn, MaxIdle: maxIdle}\n}\n\n// Get gets a connection. The application must close the returned connection.\n// This method always returns a valid connection so that applications can defer\n// error handling to the first use of the connection. If there is an error\n// getting an underlying connection, then the connection Err, Do, Send, Flush\n// and Receive methods return that error.\nfunc (p *Pool) Get() Conn {\n\t// GetContext returns errorConn in the first argument when an error occurs.\n\tc, _ := p.GetContext(context.Background())\n\treturn c\n}\n\n// GetContext gets a connection using the provided context.\n//\n// The provided Context must be non-nil. If the context expires before the\n// connection is complete, an error is returned. Any expiration on the context\n// will not affect the returned connection.\n//\n// If the function completes without error, then the application must close the\n// returned connection.\nfunc (p *Pool) GetContext(ctx context.Context) (Conn, error) {\n\t// Wait until there is a vacant connection in the pool.\n\twaited, err := p.waitVacantConn(ctx)\n\tif err != nil {\n\t\treturn errorConn{err}, err\n\t}\n\n\tp.mu.Lock()\n\n\tif waited > 0 {\n\t\tp.waitCount++\n\t\tp.waitDuration += waited\n\t}\n\n\t// Prune stale connections at the back of the idle list.\n\tif p.IdleTimeout > 0 {\n\t\tn := p.idle.count\n\t\tfor i := 0; i < n && p.idle.back != nil && p.idle.back.t.Add(p.IdleTimeout).Before(nowFunc()); i++ {\n\t\t\tpc := p.idle.back\n\t\t\tp.idle.popBack()\n\t\t\tp.mu.Unlock()\n\t\t\tpc.c.Close()\n\t\t\tp.mu.Lock()\n\t\t\tp.active--\n\t\t}\n\t}\n\n\t// Get idle connection from the front of idle list.\n\tfor p.idle.front != nil {\n\t\tpc := p.idle.front\n\t\tp.idle.popFront()\n\t\tp.mu.Unlock()\n\t\tif (p.TestOnBorrow == nil || p.TestOnBorrow(pc.c, pc.t) == nil) &&\n\t\t\t(p.MaxConnLifetime == 0 || nowFunc().Sub(pc.created) < p.MaxConnLifetime) {\n\t\t\treturn &activeConn{p: p, pc: pc}, nil\n\t\t}\n\t\tpc.c.Close()\n\t\tp.mu.Lock()\n\t\tp.active--\n\t}\n\n\t// Check for pool closed before dialing a new connection.\n\tif p.closed {\n\t\tp.mu.Unlock()\n\t\terr := errors.New(\"redigo: get on closed pool\")\n\t\treturn errorConn{err}, err\n\t}\n\n\t// Handle limit for p.Wait == false.\n\tif !p.Wait && p.MaxActive > 0 && p.active >= p.MaxActive {\n\t\tp.mu.Unlock()\n\t\treturn errorConn{ErrPoolExhausted}, ErrPoolExhausted\n\t}\n\n\tp.active++\n\tp.mu.Unlock()\n\tc, err := p.dial(ctx)\n\tif err != nil {\n\t\tp.mu.Lock()\n\t\tp.active--\n\t\tif p.ch != nil && !p.closed {\n\t\t\tp.ch <- struct{}{}\n\t\t}\n\t\tp.mu.Unlock()\n\t\treturn errorConn{err}, err\n\t}\n\treturn &activeConn{p: p, pc: &poolConn{c: c, created: nowFunc()}}, nil\n}\n\n// PoolStats contains pool statistics.\ntype PoolStats struct {\n\t// ActiveCount is the number of connections in the pool. The count includes\n\t// idle connections and connections in use.\n\tActiveCount int\n\t// IdleCount is the number of idle connections in the pool.\n\tIdleCount int\n\n\t// WaitCount is the total number of connections waited for.\n\t// This value is currently not guaranteed to be 100% accurate.\n\tWaitCount int64\n\n\t// WaitDuration is the total time blocked waiting for a new connection.\n\t// This value is currently not guaranteed to be 100% accurate.\n\tWaitDuration time.Duration\n}\n\n// Stats returns pool's statistics.\nfunc (p *Pool) Stats() PoolStats {\n\tp.mu.Lock()\n\tstats := PoolStats{\n\t\tActiveCount:  p.active,\n\t\tIdleCount:    p.idle.count,\n\t\tWaitCount:    p.waitCount,\n\t\tWaitDuration: p.waitDuration,\n\t}\n\tp.mu.Unlock()\n\n\treturn stats\n}\n\n// ActiveCount returns the number of connections in the pool. The count\n// includes idle connections and connections in use.\nfunc (p *Pool) ActiveCount() int {\n\tp.mu.Lock()\n\tactive := p.active\n\tp.mu.Unlock()\n\treturn active\n}\n\n// IdleCount returns the number of idle connections in the pool.\nfunc (p *Pool) IdleCount() int {\n\tp.mu.Lock()\n\tidle := p.idle.count\n\tp.mu.Unlock()\n\treturn idle\n}\n\n// Close releases the resources used by the pool.\nfunc (p *Pool) Close() error {\n\tp.mu.Lock()\n\tif p.closed {\n\t\tp.mu.Unlock()\n\t\treturn nil\n\t}\n\tp.closed = true\n\tp.active -= p.idle.count\n\tpc := p.idle.front\n\tp.idle.count = 0\n\tp.idle.front, p.idle.back = nil, nil\n\tif p.ch != nil {\n\t\tclose(p.ch)\n\t}\n\tp.mu.Unlock()\n\tfor ; pc != nil; pc = pc.next {\n\t\tpc.c.Close()\n\t}\n\treturn nil\n}\n\nfunc (p *Pool) lazyInit() {\n\tp.initOnce.Do(func() {\n\t\tp.ch = make(chan struct{}, p.MaxActive)\n\t\tif p.closed {\n\t\t\tclose(p.ch)\n\t\t} else {\n\t\t\tfor i := 0; i < p.MaxActive; i++ {\n\t\t\t\tp.ch <- struct{}{}\n\t\t\t}\n\t\t}\n\t})\n}\n\n// waitVacantConn waits for a vacant connection in pool if waiting\n// is enabled and pool size is limited, otherwise returns instantly.\n// If ctx expires before that, an error is returned.\n//\n// If there were no vacant connection in the pool right away it returns the time spent waiting\n// for that connection to appear in the pool.\nfunc (p *Pool) waitVacantConn(ctx context.Context) (waited time.Duration, err error) {\n\tif !p.Wait || p.MaxActive <= 0 {\n\t\t// No wait or no connection limit.\n\t\treturn 0, nil\n\t}\n\n\tp.lazyInit()\n\n\t// wait indicates if we believe it will block so its not 100% accurate\n\t// however for stats it should be good enough.\n\twait := len(p.ch) == 0\n\tvar start time.Time\n\tif wait {\n\t\tstart = time.Now()\n\t}\n\n\tselect {\n\tcase <-p.ch:\n\t\t// Additionally check that context hasn't expired while we were waiting,\n\t\t// because `select` picks a random `case` if several of them are \"ready\".\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tp.ch <- struct{}{}\n\t\t\treturn 0, ctx.Err()\n\t\tdefault:\n\t\t}\n\tcase <-ctx.Done():\n\t\treturn 0, ctx.Err()\n\t}\n\n\tif wait {\n\t\treturn time.Since(start), nil\n\t}\n\treturn 0, nil\n}\n\nfunc (p *Pool) dial(ctx context.Context) (Conn, error) {\n\tif p.DialContext != nil {\n\t\treturn p.DialContext(ctx)\n\t}\n\tif p.Dial != nil {\n\t\treturn p.Dial()\n\t}\n\treturn nil, errors.New(\"redigo: must pass Dial or DialContext to pool\")\n}\n\nfunc (p *Pool) put(pc *poolConn, forceClose bool) error {\n\tp.mu.Lock()\n\tif !p.closed && !forceClose {\n\t\tpc.t = nowFunc()\n\t\tp.idle.pushFront(pc)\n\t\tif p.idle.count > p.MaxIdle {\n\t\t\tpc = p.idle.back\n\t\t\tp.idle.popBack()\n\t\t} else {\n\t\t\tpc = nil\n\t\t}\n\t}\n\n\tif pc != nil {\n\t\tp.mu.Unlock()\n\t\tpc.c.Close()\n\t\tp.mu.Lock()\n\t\tp.active--\n\t}\n\n\tif p.ch != nil && !p.closed {\n\t\tp.ch <- struct{}{}\n\t}\n\tp.mu.Unlock()\n\treturn nil\n}\n\ntype activeConn struct {\n\tp     *Pool\n\tpc    *poolConn\n\tstate int\n}\n\nvar (\n\tsentinel     []byte\n\tsentinelOnce sync.Once\n)\n\nfunc initSentinel() {\n\tp := make([]byte, 64)\n\tif _, err := rand.Read(p); err == nil {\n\t\tsentinel = p\n\t} else {\n\t\th := sha1.New()\n\t\tio.WriteString(h, \"Oops, rand failed. Use time instead.\")       // nolint: errcheck\n\t\tio.WriteString(h, strconv.FormatInt(time.Now().UnixNano(), 10)) // nolint: errcheck\n\t\tsentinel = h.Sum(nil)\n\t}\n}\n\nfunc (ac *activeConn) firstError(errs ...error) error {\n\tfor _, err := range errs[:len(errs)-1] {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn errs[len(errs)-1]\n}\n\nfunc (ac *activeConn) Close() (err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil\n\t}\n\tac.pc = nil\n\n\tif ac.state&connectionMultiState != 0 {\n\t\terr = pc.c.Send(\"DISCARD\")\n\t\tac.state &^= (connectionMultiState | connectionWatchState)\n\t} else if ac.state&connectionWatchState != 0 {\n\t\terr = pc.c.Send(\"UNWATCH\")\n\t\tac.state &^= connectionWatchState\n\t}\n\tif ac.state&connectionSubscribeState != 0 {\n\t\terr = ac.firstError(err,\n\t\t\tpc.c.Send(\"UNSUBSCRIBE\"),\n\t\t\tpc.c.Send(\"PUNSUBSCRIBE\"),\n\t\t)\n\t\t// To detect the end of the message stream, ask the server to echo\n\t\t// a sentinel value and read until we see that value.\n\t\tsentinelOnce.Do(initSentinel)\n\t\terr = ac.firstError(err,\n\t\t\tpc.c.Send(\"ECHO\", sentinel),\n\t\t\tpc.c.Flush(),\n\t\t)\n\t\tfor {\n\t\t\tp, err2 := pc.c.Receive()\n\t\t\tif err2 != nil {\n\t\t\t\terr = ac.firstError(err, err2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) {\n\t\t\t\tac.state &^= connectionSubscribeState\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\t_, err2 := pc.c.Do(\"\")\n\treturn ac.firstError(\n\t\terr,\n\t\terr2,\n\t\tac.p.put(pc, ac.state != 0 || pc.c.Err() != nil),\n\t)\n}\n\nfunc (ac *activeConn) Err() error {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn errConnClosed\n\t}\n\treturn pc.c.Err()\n}\n\nfunc (ac *activeConn) DoContext(ctx context.Context, commandName string, args ...interface{}) (reply interface{}, err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil, errConnClosed\n\t}\n\tcwt, ok := pc.c.(ConnWithContext)\n\tif !ok {\n\t\treturn nil, errContextNotSupported\n\t}\n\tci := lookupCommandInfo(commandName)\n\tac.state = (ac.state | ci.Set) &^ ci.Clear\n\treturn cwt.DoContext(ctx, commandName, args...)\n}\n\nfunc (ac *activeConn) Do(commandName string, args ...interface{}) (reply interface{}, err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil, errConnClosed\n\t}\n\tci := lookupCommandInfo(commandName)\n\tac.state = (ac.state | ci.Set) &^ ci.Clear\n\treturn pc.c.Do(commandName, args...)\n}\n\nfunc (ac *activeConn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil, errConnClosed\n\t}\n\tcwt, ok := pc.c.(ConnWithTimeout)\n\tif !ok {\n\t\treturn nil, errTimeoutNotSupported\n\t}\n\tci := lookupCommandInfo(commandName)\n\tac.state = (ac.state | ci.Set) &^ ci.Clear\n\treturn cwt.DoWithTimeout(timeout, commandName, args...)\n}\n\nfunc (ac *activeConn) Send(commandName string, args ...interface{}) error {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn errConnClosed\n\t}\n\tci := lookupCommandInfo(commandName)\n\tac.state = (ac.state | ci.Set) &^ ci.Clear\n\treturn pc.c.Send(commandName, args...)\n}\n\nfunc (ac *activeConn) Flush() error {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn errConnClosed\n\t}\n\treturn pc.c.Flush()\n}\n\nfunc (ac *activeConn) Receive() (reply interface{}, err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil, errConnClosed\n\t}\n\treturn pc.c.Receive()\n}\n\nfunc (ac *activeConn) ReceiveContext(ctx context.Context) (reply interface{}, err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil, errConnClosed\n\t}\n\tcwt, ok := pc.c.(ConnWithContext)\n\tif !ok {\n\t\treturn nil, errContextNotSupported\n\t}\n\treturn cwt.ReceiveContext(ctx)\n}\n\nfunc (ac *activeConn) ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error) {\n\tpc := ac.pc\n\tif pc == nil {\n\t\treturn nil, errConnClosed\n\t}\n\tcwt, ok := pc.c.(ConnWithTimeout)\n\tif !ok {\n\t\treturn nil, errTimeoutNotSupported\n\t}\n\treturn cwt.ReceiveWithTimeout(timeout)\n}\n\ntype errorConn struct{ err error }\n\nfunc (ec errorConn) Do(string, ...interface{}) (interface{}, error) { return nil, ec.err }\nfunc (ec errorConn) DoContext(context.Context, string, ...interface{}) (interface{}, error) {\n\treturn nil, ec.err\n}\nfunc (ec errorConn) DoWithTimeout(time.Duration, string, ...interface{}) (interface{}, error) {\n\treturn nil, ec.err\n}\nfunc (ec errorConn) Send(string, ...interface{}) error                     { return ec.err }\nfunc (ec errorConn) Err() error                                            { return ec.err }\nfunc (ec errorConn) Close() error                                          { return nil }\nfunc (ec errorConn) Flush() error                                          { return ec.err }\nfunc (ec errorConn) Receive() (interface{}, error)                         { return nil, ec.err }\nfunc (ec errorConn) ReceiveContext(context.Context) (interface{}, error)   { return nil, ec.err }\nfunc (ec errorConn) ReceiveWithTimeout(time.Duration) (interface{}, error) { return nil, ec.err }\n\ntype idleList struct {\n\tcount       int\n\tfront, back *poolConn\n}\n\ntype poolConn struct {\n\tc          Conn\n\tt          time.Time\n\tcreated    time.Time\n\tnext, prev *poolConn\n}\n\nfunc (l *idleList) pushFront(pc *poolConn) {\n\tpc.next = l.front\n\tpc.prev = nil\n\tif l.count == 0 {\n\t\tl.back = pc\n\t} else {\n\t\tl.front.prev = pc\n\t}\n\tl.front = pc\n\tl.count++\n}\n\nfunc (l *idleList) popFront() {\n\tpc := l.front\n\tl.count--\n\tif l.count == 0 {\n\t\tl.front, l.back = nil, nil\n\t} else {\n\t\tpc.next.prev = nil\n\t\tl.front = pc.next\n\t}\n\tpc.next, pc.prev = nil, nil\n}\n\nfunc (l *idleList) popBack() {\n\tpc := l.back\n\tl.count--\n\tif l.count == 0 {\n\t\tl.front, l.back = nil, nil\n\t} else {\n\t\tpc.prev.next = nil\n\t\tl.back = pc.prev\n\t}\n\tpc.next, pc.prev = nil, nil\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/pubsub.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"time\"\n)\n\n// Subscription represents a subscribe or unsubscribe notification.\ntype Subscription struct {\n\t// Kind is \"subscribe\", \"unsubscribe\", \"psubscribe\" or \"punsubscribe\"\n\tKind string\n\n\t// The channel that was changed.\n\tChannel string\n\n\t// The current number of subscriptions for connection.\n\tCount int\n}\n\n// Message represents a message notification.\ntype Message struct {\n\t// The originating channel.\n\tChannel string\n\n\t// The matched pattern, if any\n\tPattern string\n\n\t// The message data.\n\tData []byte\n}\n\n// Pong represents a pubsub pong notification.\ntype Pong struct {\n\tData string\n}\n\n// PubSubConn wraps a Conn with convenience methods for subscribers.\ntype PubSubConn struct {\n\tConn Conn\n}\n\n// Close closes the connection.\nfunc (c PubSubConn) Close() error {\n\treturn c.Conn.Close()\n}\n\n// Subscribe subscribes the connection to the specified channels.\nfunc (c PubSubConn) Subscribe(channel ...interface{}) error {\n\tif err := c.Conn.Send(\"SUBSCRIBE\", channel...); err != nil {\n\t\treturn err\n\t}\n\treturn c.Conn.Flush()\n}\n\n// PSubscribe subscribes the connection to the given patterns.\nfunc (c PubSubConn) PSubscribe(channel ...interface{}) error {\n\tif err := c.Conn.Send(\"PSUBSCRIBE\", channel...); err != nil {\n\t\treturn err\n\t}\n\treturn c.Conn.Flush()\n}\n\n// Unsubscribe unsubscribes the connection from the given channels, or from all\n// of them if none is given.\nfunc (c PubSubConn) Unsubscribe(channel ...interface{}) error {\n\tif err := c.Conn.Send(\"UNSUBSCRIBE\", channel...); err != nil {\n\t\treturn err\n\t}\n\treturn c.Conn.Flush()\n}\n\n// PUnsubscribe unsubscribes the connection from the given patterns, or from all\n// of them if none is given.\nfunc (c PubSubConn) PUnsubscribe(channel ...interface{}) error {\n\tif err := c.Conn.Send(\"PUNSUBSCRIBE\", channel...); err != nil {\n\t\treturn err\n\t}\n\treturn c.Conn.Flush()\n}\n\n// Ping sends a PING to the server with the specified data.\n//\n// The connection must be subscribed to at least one channel or pattern when\n// calling this method.\nfunc (c PubSubConn) Ping(data string) error {\n\tif err := c.Conn.Send(\"PING\", data); err != nil {\n\t\treturn err\n\t}\n\treturn c.Conn.Flush()\n}\n\n// Receive returns a pushed message as a Subscription, Message, Pong or error.\n// The return value is intended to be used directly in a type switch as\n// illustrated in the PubSubConn example.\nfunc (c PubSubConn) Receive() interface{} {\n\treturn c.receiveInternal(c.Conn.Receive())\n}\n\n// ReceiveWithTimeout is like Receive, but it allows the application to\n// override the connection's default timeout.\nfunc (c PubSubConn) ReceiveWithTimeout(timeout time.Duration) interface{} {\n\treturn c.receiveInternal(ReceiveWithTimeout(c.Conn, timeout))\n}\n\n// ReceiveContext is like Receive, but it allows termination of the receive\n// via a Context. If the call returns due to closure of the context's Done\n// channel the underlying Conn will have been closed.\nfunc (c PubSubConn) ReceiveContext(ctx context.Context) interface{} {\n\treturn c.receiveInternal(ReceiveContext(c.Conn, ctx))\n}\n\nfunc (c PubSubConn) receiveInternal(replyArg interface{}, errArg error) interface{} {\n\treply, err := Values(replyArg, errArg)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar kind string\n\treply, err = Scan(reply, &kind)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tswitch kind {\n\tcase \"message\":\n\t\tvar m Message\n\t\tif _, err := Scan(reply, &m.Channel, &m.Data); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn m\n\tcase \"pmessage\":\n\t\tvar m Message\n\t\tif _, err := Scan(reply, &m.Pattern, &m.Channel, &m.Data); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn m\n\tcase \"subscribe\", \"psubscribe\", \"unsubscribe\", \"punsubscribe\":\n\t\ts := Subscription{Kind: kind}\n\t\tif _, err := Scan(reply, &s.Channel, &s.Count); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn s\n\tcase \"pong\":\n\t\tvar p Pong\n\t\tif _, err := Scan(reply, &p.Data); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn p\n\t}\n\treturn errors.New(\"redigo: unknown pubsub notification\")\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/redis.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"time\"\n)\n\n// Error represents an error returned in a command reply.\ntype Error string\n\nfunc (err Error) Error() string { return string(err) }\n\n// Conn represents a connection to a Redis server.\ntype Conn interface {\n\t// Close closes the connection.\n\tClose() error\n\n\t// Err returns a non-nil value when the connection is not usable.\n\tErr() error\n\n\t// Do sends a command to the server and returns the received reply.\n\t// This function will use the timeout which was set when the connection is created\n\tDo(commandName string, args ...interface{}) (reply interface{}, err error)\n\n\t// Send writes the command to the client's output buffer.\n\tSend(commandName string, args ...interface{}) error\n\n\t// Flush flushes the output buffer to the Redis server.\n\tFlush() error\n\n\t// Receive receives a single reply from the Redis server\n\tReceive() (reply interface{}, err error)\n}\n\n// Argument is the interface implemented by an object which wants to control how\n// the object is converted to Redis bulk strings.\ntype Argument interface {\n\t// RedisArg returns a value to be encoded as a bulk string per the\n\t// conversions listed in the section 'Executing Commands'.\n\t// Implementations should typically return a []byte or string.\n\tRedisArg() interface{}\n}\n\n// Scanner is implemented by an object which wants to control its value is\n// interpreted when read from Redis.\ntype Scanner interface {\n\t// RedisScan assigns a value from a Redis value. The argument src is one of\n\t// the reply types listed in the section `Executing Commands`.\n\t//\n\t// An error should be returned if the value cannot be stored without\n\t// loss of information.\n\tRedisScan(src interface{}) error\n}\n\n// ConnWithTimeout is an optional interface that allows the caller to override\n// a connection's default read timeout. This interface is useful for executing\n// the BLPOP, BRPOP, BRPOPLPUSH, XREAD and other commands that block at the\n// server.\n//\n// A connection's default read timeout is set with the DialReadTimeout dial\n// option. Applications should rely on the default timeout for commands that do\n// not block at the server.\n//\n// All of the Conn implementations in this package satisfy the ConnWithTimeout\n// interface.\n//\n// Use the DoWithTimeout and ReceiveWithTimeout helper functions to simplify\n// use of this interface.\ntype ConnWithTimeout interface {\n\tConn\n\n\t// DoWithTimeout sends a command to the server and returns the received reply.\n\t// The timeout overrides the readtimeout set when dialing the connection.\n\tDoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error)\n\n\t// ReceiveWithTimeout receives a single reply from the Redis server.\n\t// The timeout overrides the readtimeout set when dialing the connection.\n\tReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error)\n}\n\n// ConnWithContext is an optional interface that allows the caller to control the command's life with context.\ntype ConnWithContext interface {\n\tConn\n\n\t// DoContext sends a command to server and returns the received reply.\n\t// min(ctx,DialReadTimeout()) will be used as the deadline.\n\t// The connection will be closed if DialReadTimeout() timeout or ctx timeout or ctx canceled when this function is running.\n\t// DialReadTimeout() timeout return err can be checked by errors.Is(err, os.ErrDeadlineExceeded).\n\t// ctx timeout return err context.DeadlineExceeded.\n\t// ctx canceled return err context.Canceled.\n\tDoContext(ctx context.Context, commandName string, args ...interface{}) (reply interface{}, err error)\n\n\t// ReceiveContext receives a single reply from the Redis server.\n\t// min(ctx,DialReadTimeout()) will be used as the deadline.\n\t// The connection will be closed if DialReadTimeout() timeout or ctx timeout or ctx canceled when this function is running.\n\t// DialReadTimeout() timeout return err can be checked by errors.Is(err, os.ErrDeadlineExceeded).\n\t// ctx timeout return err context.DeadlineExceeded.\n\t// ctx canceled return err context.Canceled.\n\tReceiveContext(ctx context.Context) (reply interface{}, err error)\n}\n\nvar errTimeoutNotSupported = errors.New(\"redis: connection does not support ConnWithTimeout\")\nvar errContextNotSupported = errors.New(\"redis: connection does not support ConnWithContext\")\n\n// DoContext sends a command to server and returns the received reply.\n// min(ctx,DialReadTimeout()) will be used as the deadline.\n// The connection will be closed if DialReadTimeout() timeout or ctx timeout or ctx canceled when this function is running.\n// DialReadTimeout() timeout return err can be checked by errors.Is(err, os.ErrDeadlineExceeded).\n// ctx timeout return err context.DeadlineExceeded.\n// ctx canceled return err context.Canceled.\nfunc DoContext(c Conn, ctx context.Context, cmd string, args ...interface{}) (interface{}, error) {\n\tcwt, ok := c.(ConnWithContext)\n\tif !ok {\n\t\treturn nil, errContextNotSupported\n\t}\n\treturn cwt.DoContext(ctx, cmd, args...)\n}\n\n// DoWithTimeout executes a Redis command with the specified read timeout. If\n// the connection does not satisfy the ConnWithTimeout interface, then an error\n// is returned.\nfunc DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {\n\tcwt, ok := c.(ConnWithTimeout)\n\tif !ok {\n\t\treturn nil, errTimeoutNotSupported\n\t}\n\treturn cwt.DoWithTimeout(timeout, cmd, args...)\n}\n\n// ReceiveContext receives a single reply from the Redis server.\n// min(ctx,DialReadTimeout()) will be used as the deadline.\n// The connection will be closed if DialReadTimeout() timeout or ctx timeout or ctx canceled when this function is running.\n// DialReadTimeout() timeout return err can be checked by strings.Contains(e.Error(), \"io/timeout\").\n// ctx timeout return err context.DeadlineExceeded.\n// ctx canceled return err context.Canceled.\nfunc ReceiveContext(c Conn, ctx context.Context) (interface{}, error) {\n\tcwt, ok := c.(ConnWithContext)\n\tif !ok {\n\t\treturn nil, errContextNotSupported\n\t}\n\treturn cwt.ReceiveContext(ctx)\n}\n\n// ReceiveWithTimeout receives a reply with the specified read timeout. If the\n// connection does not satisfy the ConnWithTimeout interface, then an error is\n// returned.\nfunc ReceiveWithTimeout(c Conn, timeout time.Duration) (interface{}, error) {\n\tcwt, ok := c.(ConnWithTimeout)\n\tif !ok {\n\t\treturn nil, errTimeoutNotSupported\n\t}\n\treturn cwt.ReceiveWithTimeout(timeout)\n}\n\n// SlowLog represents a redis SlowLog\ntype SlowLog struct {\n\t// ID is a unique progressive identifier for every slow log entry.\n\tID int64\n\n\t// Time is the unix timestamp at which the logged command was processed.\n\tTime time.Time\n\n\t// ExecutationTime is the amount of time needed for the command execution.\n\tExecutionTime time.Duration\n\n\t// Args is the command name and arguments\n\tArgs []string\n\n\t// ClientAddr is the client IP address (4.0 only).\n\tClientAddr string\n\n\t// ClientName is the name set via the CLIENT SETNAME command (4.0 only).\n\tClientName string\n}\n\n// Latency represents a redis LATENCY LATEST.\ntype Latency struct {\n\t// Name of the latest latency spike event.\n\tName string\n\n\t// Time of the latest latency spike for the event.\n\tTime time.Time\n\n\t// Latest is the latest recorded latency for the named event.\n\tLatest time.Duration\n\n\t// Max is the maximum latency for the named event.\n\tMax time.Duration\n}\n\n// LatencyHistory represents a redis LATENCY HISTORY.\ntype LatencyHistory struct {\n\t// Time is the unix timestamp at which the event was processed.\n\tTime time.Time\n\n\t// ExecutationTime is the amount of time needed for the command execution.\n\tExecutionTime time.Duration\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/reflect.go",
    "content": "package redis\n\nimport (\n\t\"reflect\"\n\t\"runtime\"\n)\n\n// methodName returns the name of the calling method,\n// assumed to be two stack frames above.\nfunc methodName() string {\n\tpc, _, _, _ := runtime.Caller(2)\n\tf := runtime.FuncForPC(pc)\n\tif f == nil {\n\t\treturn \"unknown method\"\n\t}\n\treturn f.Name()\n}\n\n// mustBe panics if f's kind is not expected.\nfunc mustBe(v reflect.Value, expected reflect.Kind) {\n\tif v.Kind() != expected {\n\t\tpanic(&reflect.ValueError{Method: methodName(), Kind: v.Kind()})\n\t}\n}\n\n// fieldByIndexCreate returns the nested field corresponding\n// to index creating elements that are nil when stepping through.\n// It panics if v is not a struct.\nfunc fieldByIndexCreate(v reflect.Value, index []int) reflect.Value {\n\tif len(index) == 1 {\n\t\treturn v.Field(index[0])\n\t}\n\n\tmustBe(v, reflect.Struct)\n\tfor i, x := range index {\n\t\tif i > 0 {\n\t\t\tif v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {\n\t\t\t\tif v.IsNil() {\n\t\t\t\t\tv.Set(reflect.New(v.Type().Elem()))\n\t\t\t\t}\n\t\t\t\tv = v.Elem()\n\t\t\t}\n\t\t}\n\t\tv = v.Field(x)\n\t}\n\n\treturn v\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/reflect_go117.go",
    "content": "//go:build !go1.18\n// +build !go1.18\n\npackage redis\n\nimport (\n\t\"errors\"\n\t\"reflect\"\n)\n\n// fieldByIndexErr returns the nested field corresponding to index.\n// It returns an error if evaluation requires stepping through a nil\n// pointer, but panics if it must step through a field that\n// is not a struct.\nfunc fieldByIndexErr(v reflect.Value, index []int) (reflect.Value, error) {\n\tif len(index) == 1 {\n\t\treturn v.Field(index[0]), nil\n\t}\n\n\tmustBe(v, reflect.Struct)\n\tfor i, x := range index {\n\t\tif i > 0 {\n\t\t\tif v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {\n\t\t\t\tif v.IsNil() {\n\t\t\t\t\treturn reflect.Value{}, errors.New(\"reflect: indirection through nil pointer to embedded struct field \" + v.Type().Elem().Name())\n\t\t\t\t}\n\t\t\t\tv = v.Elem()\n\t\t\t}\n\t\t}\n\t\tv = v.Field(x)\n\t}\n\n\treturn v, nil\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/reflect_go118.go",
    "content": "//go:build go1.18\n// +build go1.18\n\npackage redis\n\nimport (\n\t\"reflect\"\n)\n\n// fieldByIndexErr returns the nested field corresponding to index.\n// It returns an error if evaluation requires stepping through a nil\n// pointer, but panics if it must step through a field that\n// is not a struct.\nfunc fieldByIndexErr(v reflect.Value, index []int) (reflect.Value, error) {\n\treturn v.FieldByIndexErr(index)\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/reply.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n)\n\n// ErrNil indicates that a reply value is nil.\nvar ErrNil = errors.New(\"redigo: nil returned\")\n\n// Int is a helper that converts a command reply to an integer. If err is not\n// equal to nil, then Int returns 0, err. Otherwise, Int converts the\n// reply to an int as follows:\n//\n//\tReply type    Result\n//\tinteger       int(reply), nil\n//\tbulk string   parsed reply, nil\n//\tnil           0, ErrNil\n//\tother         0, error\nfunc Int(reply interface{}, err error) (int, error) {\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase int64:\n\t\tx := int(reply)\n\t\tif int64(x) != reply {\n\t\t\treturn 0, strconv.ErrRange\n\t\t}\n\t\treturn x, nil\n\tcase []byte:\n\t\tn, err := strconv.ParseInt(string(reply), 10, 0)\n\t\treturn int(n), err\n\tcase nil:\n\t\treturn 0, ErrNil\n\tcase Error:\n\t\treturn 0, reply\n\t}\n\treturn 0, fmt.Errorf(\"redigo: unexpected type for Int, got type %T\", reply)\n}\n\n// Int64 is a helper that converts a command reply to 64 bit integer. If err is\n// not equal to nil, then Int64 returns 0, err. Otherwise, Int64 converts the\n// reply to an int64 as follows:\n//\n//\tReply type    Result\n//\tinteger       reply, nil\n//\tbulk string   parsed reply, nil\n//\tnil           0, ErrNil\n//\tother         0, error\nfunc Int64(reply interface{}, err error) (int64, error) {\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase int64:\n\t\treturn reply, nil\n\tcase []byte:\n\t\tn, err := strconv.ParseInt(string(reply), 10, 64)\n\t\treturn n, err\n\tcase nil:\n\t\treturn 0, ErrNil\n\tcase Error:\n\t\treturn 0, reply\n\t}\n\treturn 0, fmt.Errorf(\"redigo: unexpected type for Int64, got type %T\", reply)\n}\n\nfunc errNegativeInt(v int64) error {\n\treturn fmt.Errorf(\"redigo: unexpected negative value %v for Uint64\", v)\n}\n\n// Uint64 is a helper that converts a command reply to 64 bit unsigned integer.\n// If err is not equal to nil, then Uint64 returns 0, err. Otherwise, Uint64 converts the\n// reply to an uint64 as follows:\n//\n//\tReply type    Result\n//\t+integer      reply, nil\n//\tbulk string   parsed reply, nil\n//\tnil           0, ErrNil\n//\tother         0, error\nfunc Uint64(reply interface{}, err error) (uint64, error) {\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase int64:\n\t\tif reply < 0 {\n\t\t\treturn 0, errNegativeInt(reply)\n\t\t}\n\t\treturn uint64(reply), nil\n\tcase []byte:\n\t\tn, err := strconv.ParseUint(string(reply), 10, 64)\n\t\treturn n, err\n\tcase nil:\n\t\treturn 0, ErrNil\n\tcase Error:\n\t\treturn 0, reply\n\t}\n\treturn 0, fmt.Errorf(\"redigo: unexpected type for Uint64, got type %T\", reply)\n}\n\n// Float64 is a helper that converts a command reply to 64 bit float. If err is\n// not equal to nil, then Float64 returns 0, err. Otherwise, Float64 converts\n// the reply to a float64 as follows:\n//\n//\tReply type    Result\n//\tbulk string   parsed reply, nil\n//\tnil           0, ErrNil\n//\tother         0, error\nfunc Float64(reply interface{}, err error) (float64, error) {\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase []byte:\n\t\tn, err := strconv.ParseFloat(string(reply), 64)\n\t\treturn n, err\n\tcase nil:\n\t\treturn 0, ErrNil\n\tcase Error:\n\t\treturn 0, reply\n\t}\n\treturn 0, fmt.Errorf(\"redigo: unexpected type for Float64, got type %T\", reply)\n}\n\n// String is a helper that converts a command reply to a string. If err is not\n// equal to nil, then String returns \"\", err. Otherwise String converts the\n// reply to a string as follows:\n//\n//\tReply type      Result\n//\tbulk string     string(reply), nil\n//\tsimple string   reply, nil\n//\tnil             \"\",  ErrNil\n//\tother           \"\",  error\nfunc String(reply interface{}, err error) (string, error) {\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tswitch reply := reply.(type) {\n\tcase []byte:\n\t\treturn string(reply), nil\n\tcase string:\n\t\treturn reply, nil\n\tcase nil:\n\t\treturn \"\", ErrNil\n\tcase Error:\n\t\treturn \"\", reply\n\t}\n\treturn \"\", fmt.Errorf(\"redigo: unexpected type for String, got type %T\", reply)\n}\n\n// Bytes is a helper that converts a command reply to a slice of bytes. If err\n// is not equal to nil, then Bytes returns nil, err. Otherwise Bytes converts\n// the reply to a slice of bytes as follows:\n//\n//\tReply type      Result\n//\tbulk string     reply, nil\n//\tsimple string   []byte(reply), nil\n//\tnil             nil, ErrNil\n//\tother           nil, error\nfunc Bytes(reply interface{}, err error) ([]byte, error) {\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase []byte:\n\t\treturn reply, nil\n\tcase string:\n\t\treturn []byte(reply), nil\n\tcase nil:\n\t\treturn nil, ErrNil\n\tcase Error:\n\t\treturn nil, reply\n\t}\n\treturn nil, fmt.Errorf(\"redigo: unexpected type for Bytes, got type %T\", reply)\n}\n\n// Bool is a helper that converts a command reply to a boolean. If err is not\n// equal to nil, then Bool returns false, err. Otherwise Bool converts the\n// reply to boolean as follows:\n//\n//\tReply type      Result\n//\tinteger         value != 0, nil\n//\tbulk string     strconv.ParseBool(reply)\n//\tnil             false, ErrNil\n//\tother           false, error\nfunc Bool(reply interface{}, err error) (bool, error) {\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase int64:\n\t\treturn reply != 0, nil\n\tcase []byte:\n\t\treturn strconv.ParseBool(string(reply))\n\tcase nil:\n\t\treturn false, ErrNil\n\tcase Error:\n\t\treturn false, reply\n\t}\n\treturn false, fmt.Errorf(\"redigo: unexpected type for Bool, got type %T\", reply)\n}\n\n// MultiBulk is a helper that converts an array command reply to a []interface{}.\n//\n// Deprecated: Use Values instead.\nfunc MultiBulk(reply interface{}, err error) ([]interface{}, error) { return Values(reply, err) }\n\n// Values is a helper that converts an array command reply to a []interface{}.\n// If err is not equal to nil, then Values returns nil, err. Otherwise, Values\n// converts the reply as follows:\n//\n//\tReply type      Result\n//\tarray           reply, nil\n//\tnil             nil, ErrNil\n//\tother           nil, error\nfunc Values(reply interface{}, err error) ([]interface{}, error) {\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch reply := reply.(type) {\n\tcase []interface{}:\n\t\treturn reply, nil\n\tcase nil:\n\t\treturn nil, ErrNil\n\tcase Error:\n\t\treturn nil, reply\n\t}\n\treturn nil, fmt.Errorf(\"redigo: unexpected type for Values, got type %T\", reply)\n}\n\nfunc sliceHelper(reply interface{}, err error, name string, makeSlice func(int), assign func(int, interface{}) error) error {\n\tif err != nil {\n\t\treturn err\n\t}\n\tswitch reply := reply.(type) {\n\tcase []interface{}:\n\t\tmakeSlice(len(reply))\n\t\tfor i := range reply {\n\t\t\tif reply[i] == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := assign(i, reply[i]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase nil:\n\t\treturn ErrNil\n\tcase Error:\n\t\treturn reply\n\t}\n\treturn fmt.Errorf(\"redigo: unexpected type for %s, got type %T\", name, reply)\n}\n\n// Float64s is a helper that converts an array command reply to a []float64. If\n// err is not equal to nil, then Float64s returns nil, err. Nil array items are\n// converted to 0 in the output slice. Floats64 returns an error if an array\n// item is not a bulk string or nil.\nfunc Float64s(reply interface{}, err error) ([]float64, error) {\n\tvar result []float64\n\terr = sliceHelper(reply, err, \"Float64s\", func(n int) { result = make([]float64, n) }, func(i int, v interface{}) error {\n\t\tswitch v := v.(type) {\n\t\tcase []byte:\n\t\t\tf, err := strconv.ParseFloat(string(v), 64)\n\t\t\tresult[i] = f\n\t\t\treturn err\n\t\tcase Error:\n\t\t\treturn v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"redigo: unexpected element type for Float64s, got type %T\", v)\n\t\t}\n\t})\n\treturn result, err\n}\n\n// Strings is a helper that converts an array command reply to a []string. If\n// err is not equal to nil, then Strings returns nil, err. Nil array items are\n// converted to \"\" in the output slice. Strings returns an error if an array\n// item is not a bulk string or nil.\nfunc Strings(reply interface{}, err error) ([]string, error) {\n\tvar result []string\n\terr = sliceHelper(reply, err, \"Strings\", func(n int) { result = make([]string, n) }, func(i int, v interface{}) error {\n\t\tswitch v := v.(type) {\n\t\tcase string:\n\t\t\tresult[i] = v\n\t\t\treturn nil\n\t\tcase []byte:\n\t\t\tresult[i] = string(v)\n\t\t\treturn nil\n\t\tcase Error:\n\t\t\treturn v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"redigo: unexpected element type for Strings, got type %T\", v)\n\t\t}\n\t})\n\treturn result, err\n}\n\n// ByteSlices is a helper that converts an array command reply to a [][]byte.\n// If err is not equal to nil, then ByteSlices returns nil, err. Nil array\n// items are stay nil. ByteSlices returns an error if an array item is not a\n// bulk string or nil.\nfunc ByteSlices(reply interface{}, err error) ([][]byte, error) {\n\tvar result [][]byte\n\terr = sliceHelper(reply, err, \"ByteSlices\", func(n int) { result = make([][]byte, n) }, func(i int, v interface{}) error {\n\t\tswitch v := v.(type) {\n\t\tcase []byte:\n\t\t\tresult[i] = v\n\t\t\treturn nil\n\t\tcase Error:\n\t\t\treturn v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"redigo: unexpected element type for ByteSlices, got type %T\", v)\n\t\t}\n\t})\n\treturn result, err\n}\n\n// Int64s is a helper that converts an array command reply to a []int64.\n// If err is not equal to nil, then Int64s returns nil, err. Nil array\n// items are stay nil. Int64s returns an error if an array item is not a\n// bulk string or nil.\nfunc Int64s(reply interface{}, err error) ([]int64, error) {\n\tvar result []int64\n\terr = sliceHelper(reply, err, \"Int64s\", func(n int) { result = make([]int64, n) }, func(i int, v interface{}) error {\n\t\tswitch v := v.(type) {\n\t\tcase int64:\n\t\t\tresult[i] = v\n\t\t\treturn nil\n\t\tcase []byte:\n\t\t\tn, err := strconv.ParseInt(string(v), 10, 64)\n\t\t\tresult[i] = n\n\t\t\treturn err\n\t\tcase Error:\n\t\t\treturn v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"redigo: unexpected element type for Int64s, got type %T\", v)\n\t\t}\n\t})\n\treturn result, err\n}\n\n// Ints is a helper that converts an array command reply to a []int.\n// If err is not equal to nil, then Ints returns nil, err. Nil array\n// items are stay nil. Ints returns an error if an array item is not a\n// bulk string or nil.\nfunc Ints(reply interface{}, err error) ([]int, error) {\n\tvar result []int\n\terr = sliceHelper(reply, err, \"Ints\", func(n int) { result = make([]int, n) }, func(i int, v interface{}) error {\n\t\tswitch v := v.(type) {\n\t\tcase int64:\n\t\t\tn := int(v)\n\t\t\tif int64(n) != v {\n\t\t\t\treturn strconv.ErrRange\n\t\t\t}\n\t\t\tresult[i] = n\n\t\t\treturn nil\n\t\tcase []byte:\n\t\t\tn, err := strconv.Atoi(string(v))\n\t\t\tresult[i] = n\n\t\t\treturn err\n\t\tcase Error:\n\t\t\treturn v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"redigo: unexpected element type for Ints, got type %T\", v)\n\t\t}\n\t})\n\treturn result, err\n}\n\n// mapHelper builds a map from the data in reply.\nfunc mapHelper(reply interface{}, err error, name string, makeMap func(int), assign func(key string, value interface{}) error) error {\n\tvalues, err := Values(reply, err)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(values)%2 != 0 {\n\t\treturn fmt.Errorf(\"redigo: %s expects even number of values result, got %d\", name, len(values))\n\t}\n\n\tmakeMap(len(values) / 2)\n\tfor i := 0; i < len(values); i += 2 {\n\t\tkey, ok := values[i].([]byte)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"redigo: %s key[%d] not a bulk string value, got %T\", name, i, values[i])\n\t\t}\n\n\t\tif err := assign(string(key), values[i+1]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// StringMap is a helper that converts an array of strings (alternating key, value)\n// into a map[string]string. The HGETALL and CONFIG GET commands return replies in this format.\n// Requires an even number of values in result.\nfunc StringMap(reply interface{}, err error) (map[string]string, error) {\n\tvar result map[string]string\n\terr = mapHelper(reply, err, \"StringMap\",\n\t\tfunc(n int) {\n\t\t\tresult = make(map[string]string, n)\n\t\t}, func(key string, v interface{}) error {\n\t\t\tvalue, ok := v.([]byte)\n\t\t\tif !ok {\n\t\t\t\treturn fmt.Errorf(\"redigo: StringMap for %q not a bulk string value, got %T\", key, v)\n\t\t\t}\n\n\t\t\tresult[key] = string(value)\n\n\t\t\treturn nil\n\t\t},\n\t)\n\n\treturn result, err\n}\n\n// IntMap is a helper that converts an array of strings (alternating key, value)\n// into a map[string]int. The HGETALL commands return replies in this format.\n// Requires an even number of values in result.\nfunc IntMap(result interface{}, err error) (map[string]int, error) {\n\tvar m map[string]int\n\terr = mapHelper(result, err, \"IntMap\",\n\t\tfunc(n int) {\n\t\t\tm = make(map[string]int, n)\n\t\t}, func(key string, v interface{}) error {\n\t\t\tvalue, err := Int(v, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tm[key] = value\n\n\t\t\treturn nil\n\t\t},\n\t)\n\n\treturn m, err\n}\n\n// Int64Map is a helper that converts an array of strings (alternating key, value)\n// into a map[string]int64. The HGETALL commands return replies in this format.\n// Requires an even number of values in result.\nfunc Int64Map(result interface{}, err error) (map[string]int64, error) {\n\tvar m map[string]int64\n\terr = mapHelper(result, err, \"Int64Map\",\n\t\tfunc(n int) {\n\t\t\tm = make(map[string]int64, n)\n\t\t}, func(key string, v interface{}) error {\n\t\t\tvalue, err := Int64(v, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tm[key] = value\n\n\t\t\treturn nil\n\t\t},\n\t)\n\n\treturn m, err\n}\n\n// Float64Map is a helper that converts an array of strings (alternating key, value)\n// into a map[string]float64. The HGETALL commands return replies in this format.\n// Requires an even number of values in result.\nfunc Float64Map(result interface{}, err error) (map[string]float64, error) {\n\tvar m map[string]float64\n\terr = mapHelper(result, err, \"Float64Map\",\n\t\tfunc(n int) {\n\t\t\tm = make(map[string]float64, n)\n\t\t}, func(key string, v interface{}) error {\n\t\t\tvalue, err := Float64(v, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tm[key] = value\n\n\t\t\treturn nil\n\t\t},\n\t)\n\n\treturn m, err\n}\n\n// Positions is a helper that converts an array of positions (lat, long)\n// into a [][2]float64. The GEOPOS command returns replies in this format.\nfunc Positions(result interface{}, err error) ([]*[2]float64, error) {\n\tvalues, err := Values(result, err)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpositions := make([]*[2]float64, len(values))\n\tfor i := range values {\n\t\tif values[i] == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tp, ok := values[i].([]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: unexpected element type for interface slice, got type %T\", values[i])\n\t\t}\n\n\t\tif len(p) != 2 {\n\t\t\treturn nil, fmt.Errorf(\"redigo: unexpected number of values for a member position, got %d\", len(p))\n\t\t}\n\n\t\tlat, err := Float64(p[0], nil)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tlong, err := Float64(p[1], nil)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tpositions[i] = &[2]float64{lat, long}\n\t}\n\treturn positions, nil\n}\n\n// Uint64s is a helper that converts an array command reply to a []uint64.\n// If err is not equal to nil, then Uint64s returns nil, err. Nil array\n// items are stay nil. Uint64s returns an error if an array item is not a\n// bulk string or nil.\nfunc Uint64s(reply interface{}, err error) ([]uint64, error) {\n\tvar result []uint64\n\terr = sliceHelper(reply, err, \"Uint64s\", func(n int) { result = make([]uint64, n) }, func(i int, v interface{}) error {\n\t\tswitch v := v.(type) {\n\t\tcase uint64:\n\t\t\tresult[i] = v\n\t\t\treturn nil\n\t\tcase []byte:\n\t\t\tn, err := strconv.ParseUint(string(v), 10, 64)\n\t\t\tresult[i] = n\n\t\t\treturn err\n\t\tcase Error:\n\t\t\treturn v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"redigo: unexpected element type for Uint64s, got type %T\", v)\n\t\t}\n\t})\n\treturn result, err\n}\n\n// Uint64Map is a helper that converts an array of strings (alternating key, value)\n// into a map[string]uint64. The HGETALL commands return replies in this format.\n// Requires an even number of values in result.\nfunc Uint64Map(result interface{}, err error) (map[string]uint64, error) {\n\tvar m map[string]uint64\n\terr = mapHelper(result, err, \"Uint64Map\",\n\t\tfunc(n int) {\n\t\t\tm = make(map[string]uint64, n)\n\t\t}, func(key string, v interface{}) error {\n\t\t\tvalue, err := Uint64(v, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tm[key] = value\n\n\t\t\treturn nil\n\t\t},\n\t)\n\n\treturn m, err\n}\n\n// SlowLogs is a helper that parse the SLOWLOG GET command output and\n// return the array of SlowLog\nfunc SlowLogs(result interface{}, err error) ([]SlowLog, error) {\n\trawLogs, err := Values(result, err)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlogs := make([]SlowLog, len(rawLogs))\n\tfor i, e := range rawLogs {\n\t\trawLog, ok := e.([]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element is not an array, got %T\", e)\n\t\t}\n\n\t\tvar log SlowLog\n\t\tif len(rawLog) < 4 {\n\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element has %d elements, expected at least 4\", len(rawLog))\n\t\t}\n\n\t\tlog.ID, ok = rawLog[0].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element[0] not an int64, got %T\", rawLog[0])\n\t\t}\n\n\t\ttimestamp, ok := rawLog[1].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element[1] not an int64, got %T\", rawLog[1])\n\t\t}\n\n\t\tlog.Time = time.Unix(timestamp, 0)\n\t\tduration, ok := rawLog[2].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element[2] not an int64, got %T\", rawLog[2])\n\t\t}\n\n\t\tlog.ExecutionTime = time.Duration(duration) * time.Microsecond\n\n\t\tlog.Args, err = Strings(rawLog[3], nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element[3] is not array of strings: %w\", err)\n\t\t}\n\n\t\tif len(rawLog) >= 6 {\n\t\t\tlog.ClientAddr, err = String(rawLog[4], nil)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element[4] is not a string: %w\", err)\n\t\t\t}\n\n\t\t\tlog.ClientName, err = String(rawLog[5], nil)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"redigo: slowlog element[5] is not a string: %w\", err)\n\t\t\t}\n\t\t}\n\t\tlogs[i] = log\n\t}\n\treturn logs, nil\n}\n\n// Latencies is a helper that parses the LATENCY LATEST command output and\n// return the slice of Latency values.\nfunc Latencies(result interface{}, err error) ([]Latency, error) {\n\trawLatencies, err := Values(result, err)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlatencies := make([]Latency, len(rawLatencies))\n\tfor i, e := range rawLatencies {\n\t\trawLatency, ok := e.([]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latencies element is not slice, got %T\", e)\n\t\t}\n\n\t\tvar event Latency\n\t\tif len(rawLatency) != 4 {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latencies element has %d elements, expected 4\", len(rawLatency))\n\t\t}\n\n\t\tevent.Name, err = String(rawLatency[0], nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latencies element[0] is not a string: %w\", err)\n\t\t}\n\n\t\ttimestamp, ok := rawLatency[1].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latencies element[1] not an int64, got %T\", rawLatency[1])\n\t\t}\n\n\t\tevent.Time = time.Unix(timestamp, 0)\n\n\t\tlatestDuration, ok := rawLatency[2].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latencies element[2] not an int64, got %T\", rawLatency[2])\n\t\t}\n\n\t\tevent.Latest = time.Duration(latestDuration) * time.Millisecond\n\n\t\tmaxDuration, ok := rawLatency[3].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latencies element[3] not an int64, got %T\", rawLatency[3])\n\t\t}\n\n\t\tevent.Max = time.Duration(maxDuration) * time.Millisecond\n\n\t\tlatencies[i] = event\n\t}\n\n\treturn latencies, nil\n}\n\n// LatencyHistories is a helper that parse the LATENCY HISTORY command output and\n// returns a LatencyHistory slice.\nfunc LatencyHistories(result interface{}, err error) ([]LatencyHistory, error) {\n\trawLogs, err := Values(result, err)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlatencyHistories := make([]LatencyHistory, len(rawLogs))\n\tfor i, e := range rawLogs {\n\t\trawLog, ok := e.([]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latency history element is not an slice, got %T\", e)\n\t\t}\n\n\t\tvar event LatencyHistory\n\t\ttimestamp, ok := rawLog[0].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latency history element[0] not an int64, got %T\", rawLog[0])\n\t\t}\n\n\t\tevent.Time = time.Unix(timestamp, 0)\n\n\t\tduration, ok := rawLog[1].(int64)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"redigo: latency history element[1] not an int64, got %T\", rawLog[1])\n\t\t}\n\n\t\tevent.ExecutionTime = time.Duration(duration) * time.Millisecond\n\n\t\tlatencyHistories[i] = event\n\t}\n\n\treturn latencyHistories, nil\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/scan.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n)\n\nvar (\n\tscannerType = reflect.TypeOf((*Scanner)(nil)).Elem()\n)\n\nfunc ensureLen(d reflect.Value, n int) {\n\tif n > d.Cap() {\n\t\td.Set(reflect.MakeSlice(d.Type(), n, n))\n\t} else {\n\t\td.SetLen(n)\n\t}\n}\n\nfunc cannotConvert(d reflect.Value, s interface{}) error {\n\tvar sname string\n\tswitch s.(type) {\n\tcase string:\n\t\tsname = \"Redis simple string\"\n\tcase Error:\n\t\tsname = \"Redis error\"\n\tcase int64:\n\t\tsname = \"Redis integer\"\n\tcase []byte:\n\t\tsname = \"Redis bulk string\"\n\tcase []interface{}:\n\t\tsname = \"Redis array\"\n\tcase nil:\n\t\tsname = \"Redis nil\"\n\tdefault:\n\t\tsname = reflect.TypeOf(s).String()\n\t}\n\treturn fmt.Errorf(\"cannot convert from %s to %s\", sname, d.Type())\n}\n\nfunc convertAssignNil(d reflect.Value) (err error) {\n\tswitch d.Type().Kind() {\n\tcase reflect.Slice, reflect.Interface:\n\t\td.Set(reflect.Zero(d.Type()))\n\tdefault:\n\t\terr = cannotConvert(d, nil)\n\t}\n\treturn err\n}\n\nfunc convertAssignError(d reflect.Value, s Error) (err error) {\n\tif d.Kind() == reflect.String {\n\t\td.SetString(string(s))\n\t} else if d.Kind() == reflect.Slice && d.Type().Elem().Kind() == reflect.Uint8 {\n\t\td.SetBytes([]byte(s))\n\t} else {\n\t\terr = cannotConvert(d, s)\n\t}\n\treturn\n}\n\nfunc convertAssignString(d reflect.Value, s string) (err error) {\n\tswitch d.Type().Kind() {\n\tcase reflect.Float32, reflect.Float64:\n\t\tvar x float64\n\t\tx, err = strconv.ParseFloat(s, d.Type().Bits())\n\t\td.SetFloat(x)\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tvar x int64\n\t\tx, err = strconv.ParseInt(s, 10, d.Type().Bits())\n\t\td.SetInt(x)\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tvar x uint64\n\t\tx, err = strconv.ParseUint(s, 10, d.Type().Bits())\n\t\td.SetUint(x)\n\tcase reflect.Bool:\n\t\tvar x bool\n\t\tx, err = strconv.ParseBool(s)\n\t\td.SetBool(x)\n\tcase reflect.String:\n\t\td.SetString(s)\n\tcase reflect.Slice:\n\t\tif d.Type().Elem().Kind() == reflect.Uint8 {\n\t\t\td.SetBytes([]byte(s))\n\t\t} else {\n\t\t\terr = cannotConvert(d, s)\n\t\t}\n\tcase reflect.Ptr:\n\t\terr = convertAssignString(d.Elem(), s)\n\tdefault:\n\t\terr = cannotConvert(d, s)\n\t}\n\treturn\n}\n\nfunc convertAssignBulkString(d reflect.Value, s []byte) (err error) {\n\tswitch d.Type().Kind() {\n\tcase reflect.Slice:\n\t\t// Handle []byte destination here to avoid unnecessary\n\t\t// []byte -> string -> []byte converion.\n\t\tif d.Type().Elem().Kind() == reflect.Uint8 {\n\t\t\td.SetBytes(s)\n\t\t} else {\n\t\t\terr = cannotConvert(d, s)\n\t\t}\n\tcase reflect.Ptr:\n\t\tif d.CanInterface() && d.CanSet() {\n\t\t\tif s == nil {\n\t\t\t\tif d.IsNil() {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\n\t\t\t\td.Set(reflect.Zero(d.Type()))\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tif d.IsNil() {\n\t\t\t\td.Set(reflect.New(d.Type().Elem()))\n\t\t\t}\n\n\t\t\tif sc, ok := d.Interface().(Scanner); ok {\n\t\t\t\treturn sc.RedisScan(s)\n\t\t\t}\n\t\t}\n\t\terr = convertAssignString(d, string(s))\n\tdefault:\n\t\terr = convertAssignString(d, string(s))\n\t}\n\treturn err\n}\n\nfunc convertAssignInt(d reflect.Value, s int64) (err error) {\n\tswitch d.Type().Kind() {\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\td.SetInt(s)\n\t\tif d.Int() != s {\n\t\t\terr = strconv.ErrRange\n\t\t\td.SetInt(0)\n\t\t}\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tif s < 0 {\n\t\t\terr = strconv.ErrRange\n\t\t} else {\n\t\t\tx := uint64(s)\n\t\t\td.SetUint(x)\n\t\t\tif d.Uint() != x {\n\t\t\t\terr = strconv.ErrRange\n\t\t\t\td.SetUint(0)\n\t\t\t}\n\t\t}\n\tcase reflect.Bool:\n\t\td.SetBool(s != 0)\n\tdefault:\n\t\terr = cannotConvert(d, s)\n\t}\n\treturn\n}\n\nfunc convertAssignValue(d reflect.Value, s interface{}) (err error) {\n\tif d.Kind() != reflect.Ptr {\n\t\tif d.CanAddr() {\n\t\t\td2 := d.Addr()\n\t\t\tif d2.CanInterface() {\n\t\t\t\tif scanner, ok := d2.Interface().(Scanner); ok {\n\t\t\t\t\treturn scanner.RedisScan(s)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if d.CanInterface() {\n\t\t// Already a reflect.Ptr\n\t\tif d.IsNil() {\n\t\t\td.Set(reflect.New(d.Type().Elem()))\n\t\t}\n\t\tif scanner, ok := d.Interface().(Scanner); ok {\n\t\t\treturn scanner.RedisScan(s)\n\t\t}\n\t}\n\n\tswitch s := s.(type) {\n\tcase nil:\n\t\terr = convertAssignNil(d)\n\tcase []byte:\n\t\terr = convertAssignBulkString(d, s)\n\tcase int64:\n\t\terr = convertAssignInt(d, s)\n\tcase string:\n\t\terr = convertAssignString(d, s)\n\tcase Error:\n\t\terr = convertAssignError(d, s)\n\tdefault:\n\t\terr = cannotConvert(d, s)\n\t}\n\treturn err\n}\n\nfunc convertAssignArray(d reflect.Value, s []interface{}) error {\n\tif d.Type().Kind() != reflect.Slice {\n\t\treturn cannotConvert(d, s)\n\t}\n\tensureLen(d, len(s))\n\tfor i := 0; i < len(s); i++ {\n\t\tif err := convertAssignValue(d.Index(i), s[i]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc convertAssign(d interface{}, s interface{}) (err error) {\n\tif scanner, ok := d.(Scanner); ok {\n\t\treturn scanner.RedisScan(s)\n\t}\n\n\t// Handle the most common destination types using type switches and\n\t// fall back to reflection for all other types.\n\tswitch s := s.(type) {\n\tcase nil:\n\t\t// ignore\n\tcase []byte:\n\t\tswitch d := d.(type) {\n\t\tcase *string:\n\t\t\t*d = string(s)\n\t\tcase *int:\n\t\t\t*d, err = strconv.Atoi(string(s))\n\t\tcase *bool:\n\t\t\t*d, err = strconv.ParseBool(string(s))\n\t\tcase *[]byte:\n\t\t\t*d = s\n\t\tcase *interface{}:\n\t\t\t*d = s\n\t\tcase nil:\n\t\t\t// skip value\n\t\tdefault:\n\t\t\tif d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {\n\t\t\t\terr = cannotConvert(d, s)\n\t\t\t} else {\n\t\t\t\terr = convertAssignBulkString(d.Elem(), s)\n\t\t\t}\n\t\t}\n\tcase int64:\n\t\tswitch d := d.(type) {\n\t\tcase *int:\n\t\t\tx := int(s)\n\t\t\tif int64(x) != s {\n\t\t\t\terr = strconv.ErrRange\n\t\t\t\tx = 0\n\t\t\t}\n\t\t\t*d = x\n\t\tcase *bool:\n\t\t\t*d = s != 0\n\t\tcase *interface{}:\n\t\t\t*d = s\n\t\tcase nil:\n\t\t\t// skip value\n\t\tdefault:\n\t\t\tif d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {\n\t\t\t\terr = cannotConvert(d, s)\n\t\t\t} else {\n\t\t\t\terr = convertAssignInt(d.Elem(), s)\n\t\t\t}\n\t\t}\n\tcase string:\n\t\tswitch d := d.(type) {\n\t\tcase *string:\n\t\t\t*d = s\n\t\tcase *interface{}:\n\t\t\t*d = s\n\t\tcase nil:\n\t\t\t// skip value\n\t\tdefault:\n\t\t\terr = cannotConvert(reflect.ValueOf(d), s)\n\t\t}\n\tcase []interface{}:\n\t\tswitch d := d.(type) {\n\t\tcase *[]interface{}:\n\t\t\t*d = s\n\t\tcase *interface{}:\n\t\t\t*d = s\n\t\tcase nil:\n\t\t\t// skip value\n\t\tdefault:\n\t\t\tif d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {\n\t\t\t\terr = cannotConvert(d, s)\n\t\t\t} else {\n\t\t\t\terr = convertAssignArray(d.Elem(), s)\n\t\t\t}\n\t\t}\n\tcase Error:\n\t\terr = s\n\tdefault:\n\t\terr = cannotConvert(reflect.ValueOf(d), s)\n\t}\n\treturn\n}\n\n// Scan copies from src to the values pointed at by dest.\n//\n// Scan uses RedisScan if available otherwise:\n//\n// The values pointed at by dest must be an integer, float, boolean, string,\n// []byte, interface{} or slices of these types. Scan uses the standard strconv\n// package to convert bulk strings to numeric and boolean types.\n//\n// If a dest value is nil, then the corresponding src value is skipped.\n//\n// If a src element is nil, then the corresponding dest value is not modified.\n//\n// To enable easy use of Scan in a loop, Scan returns the slice of src\n// following the copied values.\nfunc Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {\n\tif len(src) < len(dest) {\n\t\treturn nil, errors.New(\"redigo.Scan: array short\")\n\t}\n\tvar err error\n\tfor i, d := range dest {\n\t\terr = convertAssign(d, src[i])\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"redigo.Scan: cannot assign to dest %d: %v\", i, err)\n\t\t\tbreak\n\t\t}\n\t}\n\treturn src[len(dest):], err\n}\n\ntype fieldSpec struct {\n\tname      string\n\tindex     []int\n\tomitEmpty bool\n}\n\ntype structSpec struct {\n\tm map[string]*fieldSpec\n\tl []*fieldSpec\n}\n\nfunc (ss *structSpec) fieldSpec(name []byte) *fieldSpec {\n\treturn ss.m[string(name)]\n}\n\nfunc compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec, seen map[reflect.Type]struct{}) error {\n\tif _, ok := seen[t]; ok {\n\t\t// Protect against infinite recursion.\n\t\treturn fmt.Errorf(\"recursive struct definition for %v\", t)\n\t}\n\n\tseen[t] = struct{}{}\nLOOP:\n\tfor i := 0; i < t.NumField(); i++ {\n\t\tf := t.Field(i)\n\t\tswitch {\n\t\tcase f.PkgPath != \"\" && !f.Anonymous:\n\t\t\t// Ignore unexported fields.\n\t\tcase f.Anonymous:\n\t\t\tswitch f.Type.Kind() {\n\t\t\tcase reflect.Struct:\n\t\t\t\tif err := compileStructSpec(f.Type, depth, append(index, i), ss, seen); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase reflect.Ptr:\n\t\t\t\tif f.Type.Elem().Kind() == reflect.Struct {\n\t\t\t\t\tif err := compileStructSpec(f.Type.Elem(), depth, append(index, i), ss, seen); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\tfs := &fieldSpec{name: f.Name}\n\t\t\ttag := f.Tag.Get(\"redis\")\n\n\t\t\tvar p string\n\t\t\tfirst := true\n\t\t\tfor len(tag) > 0 {\n\t\t\t\ti := strings.IndexByte(tag, ',')\n\t\t\t\tif i < 0 {\n\t\t\t\t\tp, tag = tag, \"\"\n\t\t\t\t} else {\n\t\t\t\t\tp, tag = tag[:i], tag[i+1:]\n\t\t\t\t}\n\t\t\t\tif p == \"-\" {\n\t\t\t\t\tcontinue LOOP\n\t\t\t\t}\n\t\t\t\tif first && len(p) > 0 {\n\t\t\t\t\tfs.name = p\n\t\t\t\t\tfirst = false\n\t\t\t\t} else {\n\t\t\t\t\tswitch p {\n\t\t\t\t\tcase \"omitempty\":\n\t\t\t\t\t\tfs.omitEmpty = true\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tpanic(fmt.Errorf(\"redigo: unknown field tag %s for type %s\", p, t.Name()))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\td, found := depth[fs.name]\n\t\t\tif !found {\n\t\t\t\td = 1 << 30\n\t\t\t}\n\n\t\t\tswitch {\n\t\t\tcase len(index) == d:\n\t\t\t\t// At same depth, remove from result.\n\t\t\t\tdelete(ss.m, fs.name)\n\t\t\t\tj := 0\n\t\t\t\tfor i := 0; i < len(ss.l); i++ {\n\t\t\t\t\tif fs.name != ss.l[i].name {\n\t\t\t\t\t\tss.l[j] = ss.l[i]\n\t\t\t\t\t\tj += 1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tss.l = ss.l[:j]\n\t\t\tcase len(index) < d:\n\t\t\t\tfs.index = make([]int, len(index)+1)\n\t\t\t\tcopy(fs.index, index)\n\t\t\t\tfs.index[len(index)] = i\n\t\t\t\tdepth[fs.name] = len(index)\n\t\t\t\tss.m[fs.name] = fs\n\t\t\t\tss.l = append(ss.l, fs)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nvar (\n\tstructSpecMutex sync.RWMutex\n\tstructSpecCache = make(map[reflect.Type]*structSpec)\n)\n\nfunc structSpecForType(t reflect.Type) (*structSpec, error) {\n\tstructSpecMutex.RLock()\n\tss, found := structSpecCache[t]\n\tstructSpecMutex.RUnlock()\n\tif found {\n\t\treturn ss, nil\n\t}\n\n\tstructSpecMutex.Lock()\n\tdefer structSpecMutex.Unlock()\n\tss, found = structSpecCache[t]\n\tif found {\n\t\treturn ss, nil\n\t}\n\n\tss = &structSpec{m: make(map[string]*fieldSpec)}\n\tif err := compileStructSpec(t, make(map[string]int), nil, ss, make(map[reflect.Type]struct{})); err != nil {\n\t\treturn nil, fmt.Errorf(\"compile struct: %s: %w\", t, err)\n\t}\n\tstructSpecCache[t] = ss\n\treturn ss, nil\n}\n\nvar errScanStructValue = errors.New(\"redigo.ScanStruct: value must be non-nil pointer to a struct\")\n\n// ScanStruct scans alternating names and values from src to a struct. The\n// HGETALL and CONFIG GET commands return replies in this format.\n//\n// ScanStruct uses exported field names to match values in the response. Use\n// 'redis' field tag to override the name:\n//\n//\tField int `redis:\"myName\"`\n//\n// Fields with the tag redis:\"-\" are ignored.\n//\n// Each field uses RedisScan if available otherwise:\n// Integer, float, boolean, string and []byte fields are supported. Scan uses the\n// standard strconv package to convert bulk string values to numeric and\n// boolean types.\n//\n// If a src element is nil, then the corresponding field is not modified.\nfunc ScanStruct(src []interface{}, dest interface{}) error {\n\td := reflect.ValueOf(dest)\n\tif d.Kind() != reflect.Ptr || d.IsNil() {\n\t\treturn errScanStructValue\n\t}\n\n\td = d.Elem()\n\tif d.Kind() != reflect.Struct {\n\t\treturn errScanStructValue\n\t}\n\n\tif len(src)%2 != 0 {\n\t\treturn errors.New(\"redigo.ScanStruct: number of values not a multiple of 2\")\n\t}\n\n\tss, err := structSpecForType(d.Type())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"redigo.ScanStruct: %w\", err)\n\t}\n\n\tfor i := 0; i < len(src); i += 2 {\n\t\ts := src[i+1]\n\t\tif s == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tname, ok := src[i].([]byte)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"redigo.ScanStruct: key %d not a bulk string value\", i)\n\t\t}\n\n\t\tfs := ss.fieldSpec(name)\n\t\tif fs == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := convertAssignValue(fieldByIndexCreate(d, fs.index), s); err != nil {\n\t\t\treturn fmt.Errorf(\"redigo.ScanStruct: cannot assign field %s: %v\", fs.name, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nvar (\n\terrScanSliceValue = errors.New(\"redigo.ScanSlice: dest must be non-nil pointer to a struct\")\n)\n\n// ScanSlice scans src to the slice pointed to by dest.\n//\n// If the target is a slice of types which implement Scanner then the custom\n// RedisScan method is used otherwise the following rules apply:\n//\n// The elements in the dest slice must be integer, float, boolean, string, struct\n// or pointer to struct values.\n//\n// Struct fields must be integer, float, boolean or string values. All struct\n// fields are used unless a subset is specified using fieldNames.\nfunc ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error {\n\td := reflect.ValueOf(dest)\n\tif d.Kind() != reflect.Ptr || d.IsNil() {\n\t\treturn errScanSliceValue\n\t}\n\td = d.Elem()\n\tif d.Kind() != reflect.Slice {\n\t\treturn errScanSliceValue\n\t}\n\n\tisPtr := false\n\tt := d.Type().Elem()\n\tst := t\n\tif t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {\n\t\tisPtr = true\n\t\tt = t.Elem()\n\t}\n\n\tif t.Kind() != reflect.Struct || st.Implements(scannerType) {\n\t\tensureLen(d, len(src))\n\t\tfor i, s := range src {\n\t\t\tif s == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := convertAssignValue(d.Index(i), s); err != nil {\n\t\t\t\treturn fmt.Errorf(\"redigo.ScanSlice: cannot assign element %d: %v\", i, err)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\tss, err := structSpecForType(t)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"redigo.ScanSlice: %w\", err)\n\t}\n\n\tfss := ss.l\n\tif len(fieldNames) > 0 {\n\t\tfss = make([]*fieldSpec, len(fieldNames))\n\t\tfor i, name := range fieldNames {\n\t\t\tfss[i] = ss.m[name]\n\t\t\tif fss[i] == nil {\n\t\t\t\treturn fmt.Errorf(\"redigo.ScanSlice: ScanSlice bad field name %s\", name)\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(fss) == 0 {\n\t\treturn errors.New(\"redigo.ScanSlice: no struct fields\")\n\t}\n\n\tn := len(src) / len(fss)\n\tif n*len(fss) != len(src) {\n\t\treturn errors.New(\"redigo.ScanSlice: length not a multiple of struct field count\")\n\t}\n\n\tensureLen(d, n)\n\tfor i := 0; i < n; i++ {\n\t\td := d.Index(i)\n\t\tif isPtr {\n\t\t\tif d.IsNil() {\n\t\t\t\td.Set(reflect.New(t))\n\t\t\t}\n\t\t\td = d.Elem()\n\t\t}\n\t\tfor j, fs := range fss {\n\t\t\ts := src[i*len(fss)+j]\n\t\t\tif s == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {\n\t\t\t\treturn fmt.Errorf(\"redigo.ScanSlice: cannot assign element %d to field %s: %v\", i*len(fss)+j, fs.name, err)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// Args is a helper for constructing command arguments from structured values.\ntype Args []interface{}\n\n// Add returns the result of appending value to args.\nfunc (args Args) Add(value ...interface{}) Args {\n\treturn append(args, value...)\n}\n\n// AddFlat returns the result of appending the flattened value of v to args.\n//\n// Maps are flattened by appending the alternating keys and map values to args.\n//\n// Slices are flattened by appending the slice elements to args.\n//\n// Structs are flattened by appending the alternating names and values of\n// exported fields to args. If v is a nil struct pointer, then nothing is\n// appended. The 'redis' field tag overrides struct field names. See ScanStruct\n// for more information on the use of the 'redis' field tag.\n//\n// Other types are appended to args as is.\n// panics if v includes a recursive anonymous struct.\nfunc (args Args) AddFlat(v interface{}) Args {\n\trv := reflect.ValueOf(v)\n\tswitch rv.Kind() {\n\tcase reflect.Struct:\n\t\targs = flattenStruct(args, rv)\n\tcase reflect.Slice:\n\t\tfor i := 0; i < rv.Len(); i++ {\n\t\t\targs = append(args, rv.Index(i).Interface())\n\t\t}\n\tcase reflect.Map:\n\t\tfor _, k := range rv.MapKeys() {\n\t\t\targs = append(args, k.Interface(), rv.MapIndex(k).Interface())\n\t\t}\n\tcase reflect.Ptr:\n\t\tif rv.Type().Elem().Kind() == reflect.Struct {\n\t\t\tif !rv.IsNil() {\n\t\t\t\targs = flattenStruct(args, rv.Elem())\n\t\t\t}\n\t\t} else {\n\t\t\targs = append(args, v)\n\t\t}\n\tdefault:\n\t\targs = append(args, v)\n\t}\n\treturn args\n}\n\nfunc flattenStruct(args Args, v reflect.Value) Args {\n\tss, err := structSpecForType(v.Type())\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"redigo.AddFlat: %w\", err))\n\t}\n\n\tfor _, fs := range ss.l {\n\t\tfv, err := fieldByIndexErr(v, fs.index)\n\t\tif err != nil {\n\t\t\t// Nil item ignore.\n\t\t\tcontinue\n\t\t}\n\t\tif fs.omitEmpty {\n\t\t\tvar empty = false\n\t\t\tswitch fv.Kind() {\n\t\t\tcase reflect.Array, reflect.Map, reflect.Slice, reflect.String:\n\t\t\t\tempty = fv.Len() == 0\n\t\t\tcase reflect.Bool:\n\t\t\t\tempty = !fv.Bool()\n\t\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\t\t\tempty = fv.Int() == 0\n\t\t\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:\n\t\t\t\tempty = fv.Uint() == 0\n\t\t\tcase reflect.Float32, reflect.Float64:\n\t\t\t\tempty = fv.Float() == 0\n\t\t\tcase reflect.Interface, reflect.Ptr:\n\t\t\t\tempty = fv.IsNil()\n\t\t\t}\n\t\t\tif empty {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif arg, ok := fv.Interface().(Argument); ok {\n\t\t\targs = append(args, fs.name, arg.RedisArg())\n\t\t} else if fv.Kind() == reflect.Ptr {\n\t\t\tif !fv.IsNil() {\n\t\t\t\targs = append(args, fs.name, fv.Elem().Interface())\n\t\t\t}\n\t\t} else {\n\t\t\targs = append(args, fs.name, fv.Interface())\n\t\t}\n\t}\n\treturn args\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gomodule/redigo/redis/script.go",
    "content": "// Copyright 2012 Gary Burd\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"): you may\n// not use this file except in compliance with the License. You may obtain\n// 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, WITHOUT\n// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n// License for the specific language governing permissions and limitations\n// under the License.\n\npackage redis\n\nimport (\n\t\"context\"\n\t\"crypto/sha1\"\n\t\"encoding/hex\"\n\t\"io\"\n\t\"strings\"\n)\n\n// Script encapsulates the source, hash and key count for a Lua script. See\n// http://redis.io/commands/eval for information on scripts in Redis.\ntype Script struct {\n\tkeyCount int\n\tsrc      string\n\thash     string\n}\n\n// NewScript returns a new script object. If keyCount is greater than or equal\n// to zero, then the count is automatically inserted in the EVAL command\n// argument list. If keyCount is less than zero, then the application supplies\n// the count as the first value in the keysAndArgs argument to the Do, Send and\n// SendHash methods.\nfunc NewScript(keyCount int, src string) *Script {\n\th := sha1.New()\n\tio.WriteString(h, src) // nolint: errcheck\n\treturn &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))}\n}\n\nfunc (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} {\n\tvar args []interface{}\n\tif s.keyCount < 0 {\n\t\targs = make([]interface{}, 1+len(keysAndArgs))\n\t\targs[0] = spec\n\t\tcopy(args[1:], keysAndArgs)\n\t} else {\n\t\targs = make([]interface{}, 2+len(keysAndArgs))\n\t\targs[0] = spec\n\t\targs[1] = s.keyCount\n\t\tcopy(args[2:], keysAndArgs)\n\t}\n\treturn args\n}\n\n// Hash returns the script hash.\nfunc (s *Script) Hash() string {\n\treturn s.hash\n}\n\nfunc (s *Script) DoContext(ctx context.Context, c Conn, keysAndArgs ...interface{}) (interface{}, error) {\n\tcwt, ok := c.(ConnWithContext)\n\tif !ok {\n\t\treturn nil, errContextNotSupported\n\t}\n\tv, err := cwt.DoContext(ctx, \"EVALSHA\", s.args(s.hash, keysAndArgs)...)\n\tif e, ok := err.(Error); ok && strings.HasPrefix(string(e), \"NOSCRIPT \") {\n\t\tv, err = cwt.DoContext(ctx, \"EVAL\", s.args(s.src, keysAndArgs)...)\n\t}\n\treturn v, err\n}\n\n// Do evaluates the script. Under the covers, Do optimistically evaluates the\n// script using the EVALSHA command. If the command fails because the script is\n// not loaded, then Do evaluates the script using the EVAL command (thus\n// causing the script to load).\nfunc (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) {\n\tv, err := c.Do(\"EVALSHA\", s.args(s.hash, keysAndArgs)...)\n\tif err != nil && strings.HasPrefix(err.Error(), \"NOSCRIPT \") {\n\t\tv, err = c.Do(\"EVAL\", s.args(s.src, keysAndArgs)...)\n\t}\n\treturn v, err\n}\n\n// SendHash evaluates the script without waiting for the reply. The script is\n// evaluated with the EVALSHA command. The application must ensure that the\n// script is loaded by a previous call to Send, Do or Load methods.\nfunc (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error {\n\treturn c.Send(\"EVALSHA\", s.args(s.hash, keysAndArgs)...)\n}\n\n// Send evaluates the script without waiting for the reply.\nfunc (s *Script) Send(c Conn, keysAndArgs ...interface{}) error {\n\treturn c.Send(\"EVAL\", s.args(s.src, keysAndArgs)...)\n}\n\n// Load loads the script without evaluating it.\nfunc (s *Script) Load(c Conn) error {\n\t_, err := c.Do(\"SCRIPT\", \"LOAD\", s.src)\n\treturn err\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/.editorconfig",
    "content": "; https://editorconfig.org/\n\nroot = true\n\n[*]\ninsert_final_newline = true\ncharset = utf-8\ntrim_trailing_whitespace = true\nindent_style = space\nindent_size = 2\n\n[{Makefile,go.mod,go.sum,*.go,.gitmodules}]\nindent_style = tab\nindent_size = 4\n\n[*.md]\nindent_size = 4\ntrim_trailing_whitespace = false\n\neclint_indent_style = unset"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/.gitignore",
    "content": "coverage.coverprofile\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/LICENSE",
    "content": "Copyright (c) 2023 The Gorilla Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n\t * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\t * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n\t * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/Makefile",
    "content": "GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '')\nGO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest\n\nGO_SEC=$(shell which gosec 2> /dev/null || echo '')\nGO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest\n\nGO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '')\nGO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest\n\n.PHONY: golangci-lint\ngolangci-lint:\n\t$(if $(GO_LINT), ,go install $(GO_LINT_URI))\n\t@echo \"##### Running golangci-lint\"\n\tgolangci-lint run -v\n\t\n.PHONY: gosec\ngosec:\n\t$(if $(GO_SEC), ,go install $(GO_SEC_URI))\n\t@echo \"##### Running gosec\"\n\tgosec ./...\n\n.PHONY: govulncheck\ngovulncheck:\n\t$(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI))\n\t@echo \"##### Running govulncheck\"\n\tgovulncheck ./...\n\n.PHONY: verify\nverify: golangci-lint gosec govulncheck\n\n.PHONY: test\ntest:\n\t@echo \"##### Running tests\"\n\tgo test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./..."
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/README.md",
    "content": "# gorilla/mux\n\n![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg)\n[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux)\n[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)\n[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)\n\n\n![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5)\n\nPackage `gorilla/mux` implements a request router and dispatcher for matching incoming requests to\ntheir respective handler.\n\nThe name mux stands for \"HTTP request multiplexer\". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are:\n\n* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`.\n* Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers.\n* URL hosts, paths and query values can have variables with an optional regular expression.\n* Registered URLs can be built, or \"reversed\", which helps maintaining references to resources.\n* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching.\n\n---\n\n* [Install](#install)\n* [Examples](#examples)\n* [Matching Routes](#matching-routes)\n* [Static Files](#static-files)\n* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.)\n* [Registered URLs](#registered-urls)\n* [Walking Routes](#walking-routes)\n* [Graceful Shutdown](#graceful-shutdown)\n* [Middleware](#middleware)\n* [Handling CORS Requests](#handling-cors-requests)\n* [Testing Handlers](#testing-handlers)\n* [Full Example](#full-example)\n\n---\n\n## Install\n\nWith a [correctly configured](https://golang.org/doc/install#testing) Go toolchain:\n\n```sh\ngo get -u github.com/gorilla/mux\n```\n\n## Examples\n\nLet's start registering a couple of URL paths and handlers:\n\n```go\nfunc main() {\n    r := mux.NewRouter()\n    r.HandleFunc(\"/\", HomeHandler)\n    r.HandleFunc(\"/products\", ProductsHandler)\n    r.HandleFunc(\"/articles\", ArticlesHandler)\n    http.Handle(\"/\", r)\n}\n```\n\nHere we register three routes mapping URL paths to handlers. This is equivalent to how `http.HandleFunc()` works: if an incoming request URL matches one of the paths, the corresponding handler is called passing (`http.ResponseWriter`, `*http.Request`) as parameters.\n\nPaths can have variables. They are defined using the format `{name}` or `{name:pattern}`. If a regular expression pattern is not defined, the matched variable will be anything until the next slash. For example:\n\n```go\nr := mux.NewRouter()\nr.HandleFunc(\"/products/{key}\", ProductHandler)\nr.HandleFunc(\"/articles/{category}/\", ArticlesCategoryHandler)\nr.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler)\n```\n\nThe names are used to create a map of route variables which can be retrieved calling `mux.Vars()`:\n\n```go\nfunc ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) {\n    vars := mux.Vars(r)\n    w.WriteHeader(http.StatusOK)\n    fmt.Fprintf(w, \"Category: %v\\n\", vars[\"category\"])\n}\n```\n\nAnd this is all you need to know about the basic usage. More advanced options are explained below.\n\n### Matching Routes\n\nRoutes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables:\n\n```go\nr := mux.NewRouter()\n// Only matches if domain is \"www.example.com\".\nr.Host(\"www.example.com\")\n// Matches a dynamic subdomain.\nr.Host(\"{subdomain:[a-z]+}.example.com\")\n```\n\nThere are several other matchers that can be added. To match path prefixes:\n\n```go\nr.PathPrefix(\"/products/\")\n```\n\n...or HTTP methods:\n\n```go\nr.Methods(\"GET\", \"POST\")\n```\n\n...or URL schemes:\n\n```go\nr.Schemes(\"https\")\n```\n\n...or header values:\n\n```go\nr.Headers(\"X-Requested-With\", \"XMLHttpRequest\")\n```\n\n...or query values:\n\n```go\nr.Queries(\"key\", \"value\")\n```\n\n...or to use a custom matcher function:\n\n```go\nr.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {\n    return r.ProtoMajor == 0\n})\n```\n\n...and finally, it is possible to combine several matchers in a single route:\n\n```go\nr.HandleFunc(\"/products\", ProductsHandler).\n  Host(\"www.example.com\").\n  Methods(\"GET\").\n  Schemes(\"http\")\n```\n\nRoutes are tested in the order they were added to the router. If two routes match, the first one wins:\n\n```go\nr := mux.NewRouter()\nr.HandleFunc(\"/specific\", specificHandler)\nr.PathPrefix(\"/\").Handler(catchAllHandler)\n```\n\nSetting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it \"subrouting\".\n\nFor example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a \"subrouter\" from it:\n\n```go\nr := mux.NewRouter()\ns := r.Host(\"www.example.com\").Subrouter()\n```\n\nThen register routes in the subrouter:\n\n```go\ns.HandleFunc(\"/products/\", ProductsHandler)\ns.HandleFunc(\"/products/{key}\", ProductHandler)\ns.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler)\n```\n\nThe three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route.\n\nSubrouters can be used to create domain or path \"namespaces\": you define subrouters in a central place and then parts of the app can register its paths relatively to a given subrouter.\n\nThere's one more thing about subroutes. When a subrouter has a path prefix, the inner routes use it as base for their paths:\n\n```go\nr := mux.NewRouter()\ns := r.PathPrefix(\"/products\").Subrouter()\n// \"/products/\"\ns.HandleFunc(\"/\", ProductsHandler)\n// \"/products/{key}/\"\ns.HandleFunc(\"/{key}/\", ProductHandler)\n// \"/products/{key}/details\"\ns.HandleFunc(\"/{key}/details\", ProductDetailsHandler)\n```\n\n\n### Static Files\n\nNote that the path provided to `PathPrefix()` represents a \"wildcard\": calling\n`PathPrefix(\"/static/\").Handler(...)` means that the handler will be passed any\nrequest that matches \"/static/\\*\". This makes it easy to serve static files with mux:\n\n```go\nfunc main() {\n    var dir string\n\n    flag.StringVar(&dir, \"dir\", \".\", \"the directory to serve files from. Defaults to the current dir\")\n    flag.Parse()\n    r := mux.NewRouter()\n\n    // This will serve files under http://localhost:8000/static/<filename>\n    r.PathPrefix(\"/static/\").Handler(http.StripPrefix(\"/static/\", http.FileServer(http.Dir(dir))))\n\n    srv := &http.Server{\n        Handler:      r,\n        Addr:         \"127.0.0.1:8000\",\n        // Good practice: enforce timeouts for servers you create!\n        WriteTimeout: 15 * time.Second,\n        ReadTimeout:  15 * time.Second,\n    }\n\n    log.Fatal(srv.ListenAndServe())\n}\n```\n\n### Serving Single Page Applications\n\nMost of the time it makes sense to serve your SPA on a separate web server from your API,\nbut sometimes it's desirable to serve them both from one place. It's possible to write a simple\nhandler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage\nmux's powerful routing for your API endpoints.\n\n```go\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/gorilla/mux\"\n)\n\n// spaHandler implements the http.Handler interface, so we can use it\n// to respond to HTTP requests. The path to the static directory and\n// path to the index file within that static directory are used to\n// serve the SPA in the given static directory.\ntype spaHandler struct {\n\tstaticPath string\n\tindexPath  string\n}\n\n// ServeHTTP inspects the URL path to locate a file within the static dir\n// on the SPA handler. If a file is found, it will be served. If not, the\n// file located at the index path on the SPA handler will be served. This\n// is suitable behavior for serving an SPA (single page application).\nfunc (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\t// Join internally call path.Clean to prevent directory traversal\n\tpath := filepath.Join(h.staticPath, r.URL.Path)\n\n\t// check whether a file exists or is a directory at the given path\n\tfi, err := os.Stat(path)\n\tif os.IsNotExist(err) || fi.IsDir() {\n\t\t// file does not exist or path is a directory, serve index.html\n\t\thttp.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))\n\t\treturn\n\t}\n\n\tif err != nil {\n\t\t// if we got an error (that wasn't that the file doesn't exist) stating the\n\t\t// file, return a 500 internal server error and stop\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n        return\n\t}\n\n\t// otherwise, use http.FileServer to serve the static file\n\thttp.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)\n}\n\nfunc main() {\n\trouter := mux.NewRouter()\n\n\trouter.HandleFunc(\"/api/health\", func(w http.ResponseWriter, r *http.Request) {\n\t\t// an example API handler\n\t\tjson.NewEncoder(w).Encode(map[string]bool{\"ok\": true})\n\t})\n\n\tspa := spaHandler{staticPath: \"build\", indexPath: \"index.html\"}\n\trouter.PathPrefix(\"/\").Handler(spa)\n\n\tsrv := &http.Server{\n\t\tHandler: router,\n\t\tAddr:    \"127.0.0.1:8000\",\n\t\t// Good practice: enforce timeouts for servers you create!\n\t\tWriteTimeout: 15 * time.Second,\n\t\tReadTimeout:  15 * time.Second,\n\t}\n\n\tlog.Fatal(srv.ListenAndServe())\n}\n```\n\n### Registered URLs\n\nNow let's see how to build registered URLs.\n\nRoutes can be named. All routes that define a name can have their URLs built, or \"reversed\". We define a name calling `Name()` on a route. For example:\n\n```go\nr := mux.NewRouter()\nr.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler).\n  Name(\"article\")\n```\n\nTo build a URL, get the route and call the `URL()` method, passing a sequence of key/value pairs for the route variables. For the previous route, we would do:\n\n```go\nurl, err := r.Get(\"article\").URL(\"category\", \"technology\", \"id\", \"42\")\n```\n\n...and the result will be a `url.URL` with the following path:\n\n```\n\"/articles/technology/42\"\n```\n\nThis also works for host and query value variables:\n\n```go\nr := mux.NewRouter()\nr.Host(\"{subdomain}.example.com\").\n  Path(\"/articles/{category}/{id:[0-9]+}\").\n  Queries(\"filter\", \"{filter}\").\n  HandlerFunc(ArticleHandler).\n  Name(\"article\")\n\n// url.String() will be \"http://news.example.com/articles/technology/42?filter=gorilla\"\nurl, err := r.Get(\"article\").URL(\"subdomain\", \"news\",\n                                 \"category\", \"technology\",\n                                 \"id\", \"42\",\n                                 \"filter\", \"gorilla\")\n```\n\nAll variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined \"build-only\" routes which never match.\n\nRegex support also exists for matching Headers within a route. For example, we could do:\n\n```go\nr.HeadersRegexp(\"Content-Type\", \"application/(text|json)\")\n```\n\n...and the route will match both requests with a Content-Type of `application/json` as well as `application/text`\n\nThere's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do:\n\n```go\n// \"http://news.example.com/\"\nhost, err := r.Get(\"article\").URLHost(\"subdomain\", \"news\")\n\n// \"/articles/technology/42\"\npath, err := r.Get(\"article\").URLPath(\"category\", \"technology\", \"id\", \"42\")\n```\n\nAnd if you use subrouters, host and path defined separately can be built as well:\n\n```go\nr := mux.NewRouter()\ns := r.Host(\"{subdomain}.example.com\").Subrouter()\ns.Path(\"/articles/{category}/{id:[0-9]+}\").\n  HandlerFunc(ArticleHandler).\n  Name(\"article\")\n\n// \"http://news.example.com/articles/technology/42\"\nurl, err := r.Get(\"article\").URL(\"subdomain\", \"news\",\n                                 \"category\", \"technology\",\n                                 \"id\", \"42\")\n```\n\nTo find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available:\n```go\nr := mux.NewRouter()\nr.Host(\"{domain}\").\n    Path(\"/{group}/{item_id}\").\n    Queries(\"some_data1\", \"{some_data1}\").\n    Queries(\"some_data2\", \"{some_data2}\").\n    Name(\"article\")\n\n// Will print [domain group item_id some_data1 some_data2] <nil>\nfmt.Println(r.Get(\"article\").GetVarNames())\n\n```\n### Walking Routes\n\nThe `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example,\nthe following prints all of the registered routes:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/gorilla/mux\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\treturn\n}\n\nfunc main() {\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handler)\n\tr.HandleFunc(\"/products\", handler).Methods(\"POST\")\n\tr.HandleFunc(\"/articles\", handler).Methods(\"GET\")\n\tr.HandleFunc(\"/articles/{id}\", handler).Methods(\"GET\", \"PUT\")\n\tr.HandleFunc(\"/authors\", handler).Queries(\"surname\", \"{surname}\")\n\terr := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {\n\t\tpathTemplate, err := route.GetPathTemplate()\n\t\tif err == nil {\n\t\t\tfmt.Println(\"ROUTE:\", pathTemplate)\n\t\t}\n\t\tpathRegexp, err := route.GetPathRegexp()\n\t\tif err == nil {\n\t\t\tfmt.Println(\"Path regexp:\", pathRegexp)\n\t\t}\n\t\tqueriesTemplates, err := route.GetQueriesTemplates()\n\t\tif err == nil {\n\t\t\tfmt.Println(\"Queries templates:\", strings.Join(queriesTemplates, \",\"))\n\t\t}\n\t\tqueriesRegexps, err := route.GetQueriesRegexp()\n\t\tif err == nil {\n\t\t\tfmt.Println(\"Queries regexps:\", strings.Join(queriesRegexps, \",\"))\n\t\t}\n\t\tmethods, err := route.GetMethods()\n\t\tif err == nil {\n\t\t\tfmt.Println(\"Methods:\", strings.Join(methods, \",\"))\n\t\t}\n\t\tfmt.Println()\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\tfmt.Println(err)\n\t}\n\n\thttp.Handle(\"/\", r)\n}\n```\n\n### Graceful Shutdown\n\nGo 1.8 introduced the ability to [gracefully shutdown](https://golang.org/doc/go1.8#http_shutdown) a `*http.Server`. Here's how to do that alongside `mux`:\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"flag\"\n    \"log\"\n    \"net/http\"\n    \"os\"\n    \"os/signal\"\n    \"time\"\n\n    \"github.com/gorilla/mux\"\n)\n\nfunc main() {\n    var wait time.Duration\n    flag.DurationVar(&wait, \"graceful-timeout\", time.Second * 15, \"the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m\")\n    flag.Parse()\n\n    r := mux.NewRouter()\n    // Add your routes as needed\n\n    srv := &http.Server{\n        Addr:         \"0.0.0.0:8080\",\n        // Good practice to set timeouts to avoid Slowloris attacks.\n        WriteTimeout: time.Second * 15,\n        ReadTimeout:  time.Second * 15,\n        IdleTimeout:  time.Second * 60,\n        Handler: r, // Pass our instance of gorilla/mux in.\n    }\n\n    // Run our server in a goroutine so that it doesn't block.\n    go func() {\n        if err := srv.ListenAndServe(); err != nil {\n            log.Println(err)\n        }\n    }()\n\n    c := make(chan os.Signal, 1)\n    // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C)\n    // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught.\n    signal.Notify(c, os.Interrupt)\n\n    // Block until we receive our signal.\n    <-c\n\n    // Create a deadline to wait for.\n    ctx, cancel := context.WithTimeout(context.Background(), wait)\n    defer cancel()\n    // Doesn't block if no connections, but will otherwise wait\n    // until the timeout deadline.\n    srv.Shutdown(ctx)\n    // Optionally, you could run srv.Shutdown in a goroutine and block on\n    // <-ctx.Done() if your application should wait for other services\n    // to finalize based on context cancellation.\n    log.Println(\"shutting down\")\n    os.Exit(0)\n}\n```\n\n### Middleware\n\nMux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters.\nMiddlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking.\n\nMux middlewares are defined using the de facto standard type:\n\n```go\ntype MiddlewareFunc func(http.Handler) http.Handler\n```\n\nTypically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers.\n\nA very basic middleware which logs the URI of the request being handled could be written as:\n\n```go\nfunc loggingMiddleware(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        // Do stuff here\n        log.Println(r.RequestURI)\n        // Call the next handler, which can be another middleware in the chain, or the final handler.\n        next.ServeHTTP(w, r)\n    })\n}\n```\n\nMiddlewares can be added to a router using `Router.Use()`:\n\n```go\nr := mux.NewRouter()\nr.HandleFunc(\"/\", handler)\nr.Use(loggingMiddleware)\n```\n\nA more complex authentication middleware, which maps session token to users, could be written as:\n\n```go\n// Define our struct\ntype authenticationMiddleware struct {\n\ttokenUsers map[string]string\n}\n\n// Initialize it somewhere\nfunc (amw *authenticationMiddleware) Populate() {\n\tamw.tokenUsers[\"00000000\"] = \"user0\"\n\tamw.tokenUsers[\"aaaaaaaa\"] = \"userA\"\n\tamw.tokenUsers[\"05f717e5\"] = \"randomUser\"\n\tamw.tokenUsers[\"deadbeef\"] = \"user0\"\n}\n\n// Middleware function, which will be called for each request\nfunc (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        token := r.Header.Get(\"X-Session-Token\")\n\n        if user, found := amw.tokenUsers[token]; found {\n        \t// We found the token in our map\n        \tlog.Printf(\"Authenticated user %s\\n\", user)\n        \t// Pass down the request to the next middleware (or final handler)\n        \tnext.ServeHTTP(w, r)\n        } else {\n        \t// Write an error and stop the handler chain\n        \thttp.Error(w, \"Forbidden\", http.StatusForbidden)\n        }\n    })\n}\n```\n\n```go\nr := mux.NewRouter()\nr.HandleFunc(\"/\", handler)\n\namw := authenticationMiddleware{tokenUsers: make(map[string]string)}\namw.Populate()\n\nr.Use(amw.Middleware)\n```\n\nNote: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it.\n\n### Handling CORS Requests\n\n[CORSMethodMiddleware](https://godoc.org/github.com/gorilla/mux#CORSMethodMiddleware) intends to make it easier to strictly set the `Access-Control-Allow-Methods` response header.\n\n* You will still need to use your own CORS handler to set the other CORS headers such as `Access-Control-Allow-Origin`\n* The middleware will set the `Access-Control-Allow-Methods` header to all the method matchers (e.g. `r.Methods(http.MethodGet, http.MethodPut, http.MethodOptions)` -> `Access-Control-Allow-Methods: GET,PUT,OPTIONS`) on a route\n* If you do not specify any methods, then:\n> _Important_: there must be an `OPTIONS` method matcher for the middleware to set the headers.\n\nHere is an example of using `CORSMethodMiddleware` along with a custom `OPTIONS` handler to set all the required CORS headers:\n\n```go\npackage main\n\nimport (\n\t\"net/http\"\n\t\"github.com/gorilla/mux\"\n)\n\nfunc main() {\n    r := mux.NewRouter()\n\n    // IMPORTANT: you must specify an OPTIONS method matcher for the middleware to set CORS headers\n    r.HandleFunc(\"/foo\", fooHandler).Methods(http.MethodGet, http.MethodPut, http.MethodPatch, http.MethodOptions)\n    r.Use(mux.CORSMethodMiddleware(r))\n    \n    http.ListenAndServe(\":8080\", r)\n}\n\nfunc fooHandler(w http.ResponseWriter, r *http.Request) {\n    w.Header().Set(\"Access-Control-Allow-Origin\", \"*\")\n    if r.Method == http.MethodOptions {\n        return\n    }\n\n    w.Write([]byte(\"foo\"))\n}\n```\n\nAnd an request to `/foo` using something like:\n\n```bash\ncurl localhost:8080/foo -v\n```\n\nWould look like:\n\n```bash\n*   Trying ::1...\n* TCP_NODELAY set\n* Connected to localhost (::1) port 8080 (#0)\n> GET /foo HTTP/1.1\n> Host: localhost:8080\n> User-Agent: curl/7.59.0\n> Accept: */*\n> \n< HTTP/1.1 200 OK\n< Access-Control-Allow-Methods: GET,PUT,PATCH,OPTIONS\n< Access-Control-Allow-Origin: *\n< Date: Fri, 28 Jun 2019 20:13:30 GMT\n< Content-Length: 3\n< Content-Type: text/plain; charset=utf-8\n< \n* Connection #0 to host localhost left intact\nfoo\n```\n\n### Testing Handlers\n\nTesting handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_.\n\nFirst, our simple HTTP handler:\n\n```go\n// endpoints.go\npackage main\n\nfunc HealthCheckHandler(w http.ResponseWriter, r *http.Request) {\n    // A very simple health check.\n    w.Header().Set(\"Content-Type\", \"application/json\")\n    w.WriteHeader(http.StatusOK)\n\n    // In the future we could report back on the status of our DB, or our cache\n    // (e.g. Redis) by performing a simple PING, and include them in the response.\n    io.WriteString(w, `{\"alive\": true}`)\n}\n\nfunc main() {\n    r := mux.NewRouter()\n    r.HandleFunc(\"/health\", HealthCheckHandler)\n\n    log.Fatal(http.ListenAndServe(\"localhost:8080\", r))\n}\n```\n\nOur test code:\n\n```go\n// endpoints_test.go\npackage main\n\nimport (\n    \"net/http\"\n    \"net/http/httptest\"\n    \"testing\"\n)\n\nfunc TestHealthCheckHandler(t *testing.T) {\n    // Create a request to pass to our handler. We don't have any query parameters for now, so we'll\n    // pass 'nil' as the third parameter.\n    req, err := http.NewRequest(\"GET\", \"/health\", nil)\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.\n    rr := httptest.NewRecorder()\n    handler := http.HandlerFunc(HealthCheckHandler)\n\n    // Our handlers satisfy http.Handler, so we can call their ServeHTTP method\n    // directly and pass in our Request and ResponseRecorder.\n    handler.ServeHTTP(rr, req)\n\n    // Check the status code is what we expect.\n    if status := rr.Code; status != http.StatusOK {\n        t.Errorf(\"handler returned wrong status code: got %v want %v\",\n            status, http.StatusOK)\n    }\n\n    // Check the response body is what we expect.\n    expected := `{\"alive\": true}`\n    if rr.Body.String() != expected {\n        t.Errorf(\"handler returned unexpected body: got %v want %v\",\n            rr.Body.String(), expected)\n    }\n}\n```\n\nIn the case that our routes have [variables](#examples), we can pass those in the request. We could write\n[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple\npossible route variables as needed.\n\n```go\n// endpoints.go\nfunc main() {\n    r := mux.NewRouter()\n    // A route with a route variable:\n    r.HandleFunc(\"/metrics/{type}\", MetricsHandler)\n\n    log.Fatal(http.ListenAndServe(\"localhost:8080\", r))\n}\n```\n\nOur test file, with a table-driven test of `routeVariables`:\n\n```go\n// endpoints_test.go\nfunc TestMetricsHandler(t *testing.T) {\n    tt := []struct{\n        routeVariable string\n        shouldPass bool\n    }{\n        {\"goroutines\", true},\n        {\"heap\", true},\n        {\"counters\", true},\n        {\"queries\", true},\n        {\"adhadaeqm3k\", false},\n    }\n\n    for _, tc := range tt {\n        path := fmt.Sprintf(\"/metrics/%s\", tc.routeVariable)\n        req, err := http.NewRequest(\"GET\", path, nil)\n        if err != nil {\n            t.Fatal(err)\n        }\n\n        rr := httptest.NewRecorder()\n\t\n\t// To add the vars to the context, \n\t// we need to create a router through which we can pass the request.\n\trouter := mux.NewRouter()\n        router.HandleFunc(\"/metrics/{type}\", MetricsHandler)\n        router.ServeHTTP(rr, req)\n\n        // In this case, our MetricsHandler returns a non-200 response\n        // for a route variable it doesn't know about.\n        if rr.Code == http.StatusOK && !tc.shouldPass {\n            t.Errorf(\"handler should have failed on routeVariable %s: got %v want %v\",\n                tc.routeVariable, rr.Code, http.StatusOK)\n        }\n    }\n}\n```\n\n## Full Example\n\nHere's a complete, runnable example of a small `mux` based server:\n\n```go\npackage main\n\nimport (\n    \"net/http\"\n    \"log\"\n    \"github.com/gorilla/mux\"\n)\n\nfunc YourHandler(w http.ResponseWriter, r *http.Request) {\n    w.Write([]byte(\"Gorilla!\\n\"))\n}\n\nfunc main() {\n    r := mux.NewRouter()\n    // Routes consist of a path and a handler function.\n    r.HandleFunc(\"/\", YourHandler)\n\n    // Bind to a port and pass our router in\n    log.Fatal(http.ListenAndServe(\":8000\", r))\n}\n```\n\n## License\n\nBSD licensed. See the LICENSE file for details.\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/doc.go",
    "content": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage mux implements a request router and dispatcher.\n\nThe name mux stands for \"HTTP request multiplexer\". Like the standard\nhttp.ServeMux, mux.Router matches incoming requests against a list of\nregistered routes and calls a handler for the route that matches the URL\nor other conditions. The main features are:\n\n  - Requests can be matched based on URL host, path, path prefix, schemes,\n    header and query values, HTTP methods or using custom matchers.\n  - URL hosts, paths and query values can have variables with an optional\n    regular expression.\n  - Registered URLs can be built, or \"reversed\", which helps maintaining\n    references to resources.\n  - Routes can be used as subrouters: nested routes are only tested if the\n    parent route matches. This is useful to define groups of routes that\n    share common conditions like a host, a path prefix or other repeated\n    attributes. As a bonus, this optimizes request matching.\n  - It implements the http.Handler interface so it is compatible with the\n    standard http.ServeMux.\n\nLet's start registering a couple of URL paths and handlers:\n\n\tfunc main() {\n\t\tr := mux.NewRouter()\n\t\tr.HandleFunc(\"/\", HomeHandler)\n\t\tr.HandleFunc(\"/products\", ProductsHandler)\n\t\tr.HandleFunc(\"/articles\", ArticlesHandler)\n\t\thttp.Handle(\"/\", r)\n\t}\n\nHere we register three routes mapping URL paths to handlers. This is\nequivalent to how http.HandleFunc() works: if an incoming request URL matches\none of the paths, the corresponding handler is called passing\n(http.ResponseWriter, *http.Request) as parameters.\n\nPaths can have variables. They are defined using the format {name} or\n{name:pattern}. If a regular expression pattern is not defined, the matched\nvariable will be anything until the next slash. For example:\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/products/{key}\", ProductHandler)\n\tr.HandleFunc(\"/articles/{category}/\", ArticlesCategoryHandler)\n\tr.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler)\n\nGroups can be used inside patterns, as long as they are non-capturing (?:re). For example:\n\n\tr.HandleFunc(\"/articles/{category}/{sort:(?:asc|desc|new)}\", ArticlesCategoryHandler)\n\nThe names are used to create a map of route variables which can be retrieved\ncalling mux.Vars():\n\n\tvars := mux.Vars(request)\n\tcategory := vars[\"category\"]\n\nNote that if any capturing groups are present, mux will panic() during parsing. To prevent\nthis, convert any capturing groups to non-capturing, e.g. change \"/{sort:(asc|desc)}\" to\n\"/{sort:(?:asc|desc)}\". This is a change from prior versions which behaved unpredictably\nwhen capturing groups were present.\n\nAnd this is all you need to know about the basic usage. More advanced options\nare explained below.\n\nRoutes can also be restricted to a domain or subdomain. Just define a host\npattern to be matched. They can also have variables:\n\n\tr := mux.NewRouter()\n\t// Only matches if domain is \"www.example.com\".\n\tr.Host(\"www.example.com\")\n\t// Matches a dynamic subdomain.\n\tr.Host(\"{subdomain:[a-z]+}.domain.com\")\n\nThere are several other matchers that can be added. To match path prefixes:\n\n\tr.PathPrefix(\"/products/\")\n\n...or HTTP methods:\n\n\tr.Methods(\"GET\", \"POST\")\n\n...or URL schemes:\n\n\tr.Schemes(\"https\")\n\n...or header values:\n\n\tr.Headers(\"X-Requested-With\", \"XMLHttpRequest\")\n\n...or query values:\n\n\tr.Queries(\"key\", \"value\")\n\n...or to use a custom matcher function:\n\n\tr.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {\n\t\treturn r.ProtoMajor == 0\n\t})\n\n...and finally, it is possible to combine several matchers in a single route:\n\n\tr.HandleFunc(\"/products\", ProductsHandler).\n\t  Host(\"www.example.com\").\n\t  Methods(\"GET\").\n\t  Schemes(\"http\")\n\nSetting the same matching conditions again and again can be boring, so we have\na way to group several routes that share the same requirements.\nWe call it \"subrouting\".\n\nFor example, let's say we have several URLs that should only match when the\nhost is \"www.example.com\". Create a route for that host and get a \"subrouter\"\nfrom it:\n\n\tr := mux.NewRouter()\n\ts := r.Host(\"www.example.com\").Subrouter()\n\nThen register routes in the subrouter:\n\n\ts.HandleFunc(\"/products/\", ProductsHandler)\n\ts.HandleFunc(\"/products/{key}\", ProductHandler)\n\ts.HandleFunc(\"/articles/{category}/{id:[0-9]+}\"), ArticleHandler)\n\nThe three URL paths we registered above will only be tested if the domain is\n\"www.example.com\", because the subrouter is tested first. This is not\nonly convenient, but also optimizes request matching. You can create\nsubrouters combining any attribute matchers accepted by a route.\n\nSubrouters can be used to create domain or path \"namespaces\": you define\nsubrouters in a central place and then parts of the app can register its\npaths relatively to a given subrouter.\n\nThere's one more thing about subroutes. When a subrouter has a path prefix,\nthe inner routes use it as base for their paths:\n\n\tr := mux.NewRouter()\n\ts := r.PathPrefix(\"/products\").Subrouter()\n\t// \"/products/\"\n\ts.HandleFunc(\"/\", ProductsHandler)\n\t// \"/products/{key}/\"\n\ts.HandleFunc(\"/{key}/\", ProductHandler)\n\t// \"/products/{key}/details\"\n\ts.HandleFunc(\"/{key}/details\", ProductDetailsHandler)\n\nNote that the path provided to PathPrefix() represents a \"wildcard\": calling\nPathPrefix(\"/static/\").Handler(...) means that the handler will be passed any\nrequest that matches \"/static/*\". This makes it easy to serve static files with mux:\n\n\tfunc main() {\n\t\tvar dir string\n\n\t\tflag.StringVar(&dir, \"dir\", \".\", \"the directory to serve files from. Defaults to the current dir\")\n\t\tflag.Parse()\n\t\tr := mux.NewRouter()\n\n\t\t// This will serve files under http://localhost:8000/static/<filename>\n\t\tr.PathPrefix(\"/static/\").Handler(http.StripPrefix(\"/static/\", http.FileServer(http.Dir(dir))))\n\n\t\tsrv := &http.Server{\n\t\t\tHandler:      r,\n\t\t\tAddr:         \"127.0.0.1:8000\",\n\t\t\t// Good practice: enforce timeouts for servers you create!\n\t\t\tWriteTimeout: 15 * time.Second,\n\t\t\tReadTimeout:  15 * time.Second,\n\t\t}\n\n\t\tlog.Fatal(srv.ListenAndServe())\n\t}\n\nNow let's see how to build registered URLs.\n\nRoutes can be named. All routes that define a name can have their URLs built,\nor \"reversed\". We define a name calling Name() on a route. For example:\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler).\n\t  Name(\"article\")\n\nTo build a URL, get the route and call the URL() method, passing a sequence of\nkey/value pairs for the route variables. For the previous route, we would do:\n\n\turl, err := r.Get(\"article\").URL(\"category\", \"technology\", \"id\", \"42\")\n\n...and the result will be a url.URL with the following path:\n\n\t\"/articles/technology/42\"\n\nThis also works for host and query value variables:\n\n\tr := mux.NewRouter()\n\tr.Host(\"{subdomain}.domain.com\").\n\t  Path(\"/articles/{category}/{id:[0-9]+}\").\n\t  Queries(\"filter\", \"{filter}\").\n\t  HandlerFunc(ArticleHandler).\n\t  Name(\"article\")\n\n\t// url.String() will be \"http://news.domain.com/articles/technology/42?filter=gorilla\"\n\turl, err := r.Get(\"article\").URL(\"subdomain\", \"news\",\n\t                                 \"category\", \"technology\",\n\t                                 \"id\", \"42\",\n\t                                 \"filter\", \"gorilla\")\n\nAll variables defined in the route are required, and their values must\nconform to the corresponding patterns. These requirements guarantee that a\ngenerated URL will always match a registered route -- the only exception is\nfor explicitly defined \"build-only\" routes which never match.\n\nRegex support also exists for matching Headers within a route. For example, we could do:\n\n\tr.HeadersRegexp(\"Content-Type\", \"application/(text|json)\")\n\n...and the route will match both requests with a Content-Type of `application/json` as well as\n`application/text`\n\nThere's also a way to build only the URL host or path for a route:\nuse the methods URLHost() or URLPath() instead. For the previous route,\nwe would do:\n\n\t// \"http://news.domain.com/\"\n\thost, err := r.Get(\"article\").URLHost(\"subdomain\", \"news\")\n\n\t// \"/articles/technology/42\"\n\tpath, err := r.Get(\"article\").URLPath(\"category\", \"technology\", \"id\", \"42\")\n\nAnd if you use subrouters, host and path defined separately can be built\nas well:\n\n\tr := mux.NewRouter()\n\ts := r.Host(\"{subdomain}.domain.com\").Subrouter()\n\ts.Path(\"/articles/{category}/{id:[0-9]+}\").\n\t  HandlerFunc(ArticleHandler).\n\t  Name(\"article\")\n\n\t// \"http://news.domain.com/articles/technology/42\"\n\turl, err := r.Get(\"article\").URL(\"subdomain\", \"news\",\n\t                                 \"category\", \"technology\",\n\t                                 \"id\", \"42\")\n\nMux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking.\n\n\ttype MiddlewareFunc func(http.Handler) http.Handler\n\nTypically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created).\n\nA very basic middleware which logs the URI of the request being handled could be written as:\n\n\tfunc simpleMw(next http.Handler) http.Handler {\n\t\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t\t// Do stuff here\n\t\t\tlog.Println(r.RequestURI)\n\t\t\t// Call the next handler, which can be another middleware in the chain, or the final handler.\n\t\t\tnext.ServeHTTP(w, r)\n\t\t})\n\t}\n\nMiddlewares can be added to a router using `Router.Use()`:\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handler)\n\tr.Use(simpleMw)\n\nA more complex authentication middleware, which maps session token to users, could be written as:\n\n\t// Define our struct\n\ttype authenticationMiddleware struct {\n\t\ttokenUsers map[string]string\n\t}\n\n\t// Initialize it somewhere\n\tfunc (amw *authenticationMiddleware) Populate() {\n\t\tamw.tokenUsers[\"00000000\"] = \"user0\"\n\t\tamw.tokenUsers[\"aaaaaaaa\"] = \"userA\"\n\t\tamw.tokenUsers[\"05f717e5\"] = \"randomUser\"\n\t\tamw.tokenUsers[\"deadbeef\"] = \"user0\"\n\t}\n\n\t// Middleware function, which will be called for each request\n\tfunc (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler {\n\t\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t\ttoken := r.Header.Get(\"X-Session-Token\")\n\n\t\t\tif user, found := amw.tokenUsers[token]; found {\n\t\t\t\t// We found the token in our map\n\t\t\t\tlog.Printf(\"Authenticated user %s\\n\", user)\n\t\t\t\tnext.ServeHTTP(w, r)\n\t\t\t} else {\n\t\t\t\thttp.Error(w, \"Forbidden\", http.StatusForbidden)\n\t\t\t}\n\t\t})\n\t}\n\n\tr := mux.NewRouter()\n\tr.HandleFunc(\"/\", handler)\n\n\tamw := authenticationMiddleware{tokenUsers: make(map[string]string)}\n\tamw.Populate()\n\n\tr.Use(amw.Middleware)\n\nNote: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to.\n*/\npackage mux\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/middleware.go",
    "content": "package mux\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n)\n\n// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler.\n// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed\n// to it, and then calls the handler passed as parameter to the MiddlewareFunc.\ntype MiddlewareFunc func(http.Handler) http.Handler\n\n// middleware interface is anything which implements a MiddlewareFunc named Middleware.\ntype middleware interface {\n\tMiddleware(handler http.Handler) http.Handler\n}\n\n// Middleware allows MiddlewareFunc to implement the middleware interface.\nfunc (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler {\n\treturn mw(handler)\n}\n\n// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.\nfunc (r *Router) Use(mwf ...MiddlewareFunc) {\n\tfor _, fn := range mwf {\n\t\tr.middlewares = append(r.middlewares, fn)\n\t}\n}\n\n// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.\nfunc (r *Router) useInterface(mw middleware) {\n\tr.middlewares = append(r.middlewares, mw)\n}\n\n// CORSMethodMiddleware automatically sets the Access-Control-Allow-Methods response header\n// on requests for routes that have an OPTIONS method matcher to all the method matchers on\n// the route. Routes that do not explicitly handle OPTIONS requests will not be processed\n// by the middleware. See examples for usage.\nfunc CORSMethodMiddleware(r *Router) MiddlewareFunc {\n\treturn func(next http.Handler) http.Handler {\n\t\treturn http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {\n\t\t\tallMethods, err := getAllMethodsForRoute(r, req)\n\t\t\tif err == nil {\n\t\t\t\tfor _, v := range allMethods {\n\t\t\t\t\tif v == http.MethodOptions {\n\t\t\t\t\t\tw.Header().Set(\"Access-Control-Allow-Methods\", strings.Join(allMethods, \",\"))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnext.ServeHTTP(w, req)\n\t\t})\n\t}\n}\n\n// getAllMethodsForRoute returns all the methods from method matchers matching a given\n// request.\nfunc getAllMethodsForRoute(r *Router, req *http.Request) ([]string, error) {\n\tvar allMethods []string\n\n\tfor _, route := range r.routes {\n\t\tvar match RouteMatch\n\t\tif route.Match(req, &match) || match.MatchErr == ErrMethodMismatch {\n\t\t\tmethods, err := route.GetMethods()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tallMethods = append(allMethods, methods...)\n\t\t}\n\t}\n\n\treturn allMethods, nil\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/mux.go",
    "content": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mux\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"path\"\n\t\"regexp\"\n)\n\nvar (\n\t// ErrMethodMismatch is returned when the method in the request does not match\n\t// the method defined against the route.\n\tErrMethodMismatch = errors.New(\"method is not allowed\")\n\t// ErrNotFound is returned when no route match is found.\n\tErrNotFound = errors.New(\"no matching route was found\")\n)\n\n// NewRouter returns a new router instance.\nfunc NewRouter() *Router {\n\treturn &Router{namedRoutes: make(map[string]*Route)}\n}\n\n// Router registers routes to be matched and dispatches a handler.\n//\n// It implements the http.Handler interface, so it can be registered to serve\n// requests:\n//\n//\tvar router = mux.NewRouter()\n//\n//\tfunc main() {\n//\t    http.Handle(\"/\", router)\n//\t}\n//\n// Or, for Google App Engine, register it in a init() function:\n//\n//\tfunc init() {\n//\t    http.Handle(\"/\", router)\n//\t}\n//\n// This will send all incoming requests to the router.\ntype Router struct {\n\t// Configurable Handler to be used when no route matches.\n\t// This can be used to render your own 404 Not Found errors.\n\tNotFoundHandler http.Handler\n\n\t// Configurable Handler to be used when the request method does not match the route.\n\t// This can be used to render your own 405 Method Not Allowed errors.\n\tMethodNotAllowedHandler http.Handler\n\n\t// Routes to be matched, in order.\n\troutes []*Route\n\n\t// Routes by name for URL building.\n\tnamedRoutes map[string]*Route\n\n\t// If true, do not clear the request context after handling the request.\n\t//\n\t// Deprecated: No effect, since the context is stored on the request itself.\n\tKeepContext bool\n\n\t// Slice of middlewares to be called after a match is found\n\tmiddlewares []middleware\n\n\t// configuration shared with `Route`\n\trouteConf\n}\n\n// common route configuration shared between `Router` and `Route`\ntype routeConf struct {\n\t// If true, \"/path/foo%2Fbar/to\" will match the path \"/path/{var}/to\"\n\tuseEncodedPath bool\n\n\t// If true, when the path pattern is \"/path/\", accessing \"/path\" will\n\t// redirect to the former and vice versa.\n\tstrictSlash bool\n\n\t// If true, when the path pattern is \"/path//to\", accessing \"/path//to\"\n\t// will not redirect\n\tskipClean bool\n\n\t// Manager for the variables from host and path.\n\tregexp routeRegexpGroup\n\n\t// List of matchers.\n\tmatchers []matcher\n\n\t// The scheme used when building URLs.\n\tbuildScheme string\n\n\tbuildVarsFunc BuildVarsFunc\n}\n\n// returns an effective deep copy of `routeConf`\nfunc copyRouteConf(r routeConf) routeConf {\n\tc := r\n\n\tif r.regexp.path != nil {\n\t\tc.regexp.path = copyRouteRegexp(r.regexp.path)\n\t}\n\n\tif r.regexp.host != nil {\n\t\tc.regexp.host = copyRouteRegexp(r.regexp.host)\n\t}\n\n\tc.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries))\n\tfor _, q := range r.regexp.queries {\n\t\tc.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q))\n\t}\n\n\tc.matchers = make([]matcher, len(r.matchers))\n\tcopy(c.matchers, r.matchers)\n\n\treturn c\n}\n\nfunc copyRouteRegexp(r *routeRegexp) *routeRegexp {\n\tc := *r\n\treturn &c\n}\n\n// Match attempts to match the given request against the router's registered routes.\n//\n// If the request matches a route of this router or one of its subrouters the Route,\n// Handler, and Vars fields of the the match argument are filled and this function\n// returns true.\n//\n// If the request does not match any of this router's or its subrouters' routes\n// then this function returns false. If available, a reason for the match failure\n// will be filled in the match argument's MatchErr field. If the match failure type\n// (eg: not found) has a registered handler, the handler is assigned to the Handler\n// field of the match argument.\nfunc (r *Router) Match(req *http.Request, match *RouteMatch) bool {\n\tfor _, route := range r.routes {\n\t\tif route.Match(req, match) {\n\t\t\t// Build middleware chain if no error was found\n\t\t\tif match.MatchErr == nil {\n\t\t\t\tfor i := len(r.middlewares) - 1; i >= 0; i-- {\n\t\t\t\t\tmatch.Handler = r.middlewares[i].Middleware(match.Handler)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t}\n\n\tif match.MatchErr == ErrMethodMismatch {\n\t\tif r.MethodNotAllowedHandler != nil {\n\t\t\tmatch.Handler = r.MethodNotAllowedHandler\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t// Closest match for a router (includes sub-routers)\n\tif r.NotFoundHandler != nil {\n\t\tmatch.Handler = r.NotFoundHandler\n\t\tmatch.MatchErr = ErrNotFound\n\t\treturn true\n\t}\n\n\tmatch.MatchErr = ErrNotFound\n\treturn false\n}\n\n// ServeHTTP dispatches the handler registered in the matched route.\n//\n// When there is a match, the route variables can be retrieved calling\n// mux.Vars(request).\nfunc (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\tif !r.skipClean {\n\t\tpath := req.URL.Path\n\t\tif r.useEncodedPath {\n\t\t\tpath = req.URL.EscapedPath()\n\t\t}\n\t\t// Clean path to canonical form and redirect.\n\t\tif p := cleanPath(path); p != path {\n\n\t\t\t// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.\n\t\t\t// This matches with fix in go 1.2 r.c. 4 for same problem.  Go Issue:\n\t\t\t// http://code.google.com/p/go/issues/detail?id=5252\n\t\t\turl := *req.URL\n\t\t\turl.Path = p\n\t\t\tp = url.String()\n\n\t\t\tw.Header().Set(\"Location\", p)\n\t\t\tw.WriteHeader(http.StatusMovedPermanently)\n\t\t\treturn\n\t\t}\n\t}\n\tvar match RouteMatch\n\tvar handler http.Handler\n\tif r.Match(req, &match) {\n\t\thandler = match.Handler\n\t\treq = requestWithVars(req, match.Vars)\n\t\treq = requestWithRoute(req, match.Route)\n\t}\n\n\tif handler == nil && match.MatchErr == ErrMethodMismatch {\n\t\thandler = methodNotAllowedHandler()\n\t}\n\n\tif handler == nil {\n\t\thandler = http.NotFoundHandler()\n\t}\n\n\thandler.ServeHTTP(w, req)\n}\n\n// Get returns a route registered with the given name.\nfunc (r *Router) Get(name string) *Route {\n\treturn r.namedRoutes[name]\n}\n\n// GetRoute returns a route registered with the given name. This method\n// was renamed to Get() and remains here for backwards compatibility.\nfunc (r *Router) GetRoute(name string) *Route {\n\treturn r.namedRoutes[name]\n}\n\n// StrictSlash defines the trailing slash behavior for new routes. The initial\n// value is false.\n//\n// When true, if the route path is \"/path/\", accessing \"/path\" will perform a redirect\n// to the former and vice versa. In other words, your application will always\n// see the path as specified in the route.\n//\n// When false, if the route path is \"/path\", accessing \"/path/\" will not match\n// this route and vice versa.\n//\n// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for\n// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed\n// request will be made as a GET by most clients. Use middleware or client settings\n// to modify this behaviour as needed.\n//\n// Special case: when a route sets a path prefix using the PathPrefix() method,\n// strict slash is ignored for that route because the redirect behavior can't\n// be determined from a prefix alone. However, any subrouters created from that\n// route inherit the original StrictSlash setting.\nfunc (r *Router) StrictSlash(value bool) *Router {\n\tr.strictSlash = value\n\treturn r\n}\n\n// SkipClean defines the path cleaning behaviour for new routes. The initial\n// value is false. Users should be careful about which routes are not cleaned\n//\n// When true, if the route path is \"/path//to\", it will remain with the double\n// slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/\n//\n// When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will\n// become /fetch/http/xkcd.com/534\nfunc (r *Router) SkipClean(value bool) *Router {\n\tr.skipClean = value\n\treturn r\n}\n\n// UseEncodedPath tells the router to match the encoded original path\n// to the routes.\n// For eg. \"/path/foo%2Fbar/to\" will match the path \"/path/{var}/to\".\n//\n// If not called, the router will match the unencoded path to the routes.\n// For eg. \"/path/foo%2Fbar/to\" will match the path \"/path/foo/bar/to\"\nfunc (r *Router) UseEncodedPath() *Router {\n\tr.useEncodedPath = true\n\treturn r\n}\n\n// ----------------------------------------------------------------------------\n// Route factories\n// ----------------------------------------------------------------------------\n\n// NewRoute registers an empty route.\nfunc (r *Router) NewRoute() *Route {\n\t// initialize a route with a copy of the parent router's configuration\n\troute := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}\n\tr.routes = append(r.routes, route)\n\treturn route\n}\n\n// Name registers a new route with a name.\n// See Route.Name().\nfunc (r *Router) Name(name string) *Route {\n\treturn r.NewRoute().Name(name)\n}\n\n// Handle registers a new route with a matcher for the URL path.\n// See Route.Path() and Route.Handler().\nfunc (r *Router) Handle(path string, handler http.Handler) *Route {\n\treturn r.NewRoute().Path(path).Handler(handler)\n}\n\n// HandleFunc registers a new route with a matcher for the URL path.\n// See Route.Path() and Route.HandlerFunc().\nfunc (r *Router) HandleFunc(path string, f func(http.ResponseWriter,\n\t*http.Request)) *Route {\n\treturn r.NewRoute().Path(path).HandlerFunc(f)\n}\n\n// Headers registers a new route with a matcher for request header values.\n// See Route.Headers().\nfunc (r *Router) Headers(pairs ...string) *Route {\n\treturn r.NewRoute().Headers(pairs...)\n}\n\n// Host registers a new route with a matcher for the URL host.\n// See Route.Host().\nfunc (r *Router) Host(tpl string) *Route {\n\treturn r.NewRoute().Host(tpl)\n}\n\n// MatcherFunc registers a new route with a custom matcher function.\n// See Route.MatcherFunc().\nfunc (r *Router) MatcherFunc(f MatcherFunc) *Route {\n\treturn r.NewRoute().MatcherFunc(f)\n}\n\n// Methods registers a new route with a matcher for HTTP methods.\n// See Route.Methods().\nfunc (r *Router) Methods(methods ...string) *Route {\n\treturn r.NewRoute().Methods(methods...)\n}\n\n// Path registers a new route with a matcher for the URL path.\n// See Route.Path().\nfunc (r *Router) Path(tpl string) *Route {\n\treturn r.NewRoute().Path(tpl)\n}\n\n// PathPrefix registers a new route with a matcher for the URL path prefix.\n// See Route.PathPrefix().\nfunc (r *Router) PathPrefix(tpl string) *Route {\n\treturn r.NewRoute().PathPrefix(tpl)\n}\n\n// Queries registers a new route with a matcher for URL query values.\n// See Route.Queries().\nfunc (r *Router) Queries(pairs ...string) *Route {\n\treturn r.NewRoute().Queries(pairs...)\n}\n\n// Schemes registers a new route with a matcher for URL schemes.\n// See Route.Schemes().\nfunc (r *Router) Schemes(schemes ...string) *Route {\n\treturn r.NewRoute().Schemes(schemes...)\n}\n\n// BuildVarsFunc registers a new route with a custom function for modifying\n// route variables before building a URL.\nfunc (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {\n\treturn r.NewRoute().BuildVarsFunc(f)\n}\n\n// Walk walks the router and all its sub-routers, calling walkFn for each route\n// in the tree. The routes are walked in the order they were added. Sub-routers\n// are explored depth-first.\nfunc (r *Router) Walk(walkFn WalkFunc) error {\n\treturn r.walk(walkFn, []*Route{})\n}\n\n// SkipRouter is used as a return value from WalkFuncs to indicate that the\n// router that walk is about to descend down to should be skipped.\nvar SkipRouter = errors.New(\"skip this router\")\n\n// WalkFunc is the type of the function called for each route visited by Walk.\n// At every invocation, it is given the current route, and the current router,\n// and a list of ancestor routes that lead to the current route.\ntype WalkFunc func(route *Route, router *Router, ancestors []*Route) error\n\nfunc (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {\n\tfor _, t := range r.routes {\n\t\terr := walkFn(t, r, ancestors)\n\t\tif err == SkipRouter {\n\t\t\tcontinue\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, sr := range t.matchers {\n\t\t\tif h, ok := sr.(*Router); ok {\n\t\t\t\tancestors = append(ancestors, t)\n\t\t\t\terr := h.walk(walkFn, ancestors)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tancestors = ancestors[:len(ancestors)-1]\n\t\t\t}\n\t\t}\n\t\tif h, ok := t.handler.(*Router); ok {\n\t\t\tancestors = append(ancestors, t)\n\t\t\terr := h.walk(walkFn, ancestors)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tancestors = ancestors[:len(ancestors)-1]\n\t\t}\n\t}\n\treturn nil\n}\n\n// ----------------------------------------------------------------------------\n// Context\n// ----------------------------------------------------------------------------\n\n// RouteMatch stores information about a matched route.\ntype RouteMatch struct {\n\tRoute   *Route\n\tHandler http.Handler\n\tVars    map[string]string\n\n\t// MatchErr is set to appropriate matching error\n\t// It is set to ErrMethodMismatch if there is a mismatch in\n\t// the request method and route method\n\tMatchErr error\n}\n\ntype contextKey int\n\nconst (\n\tvarsKey contextKey = iota\n\trouteKey\n)\n\n// Vars returns the route variables for the current request, if any.\nfunc Vars(r *http.Request) map[string]string {\n\tif rv := r.Context().Value(varsKey); rv != nil {\n\t\treturn rv.(map[string]string)\n\t}\n\treturn nil\n}\n\n// CurrentRoute returns the matched route for the current request, if any.\n// This only works when called inside the handler of the matched route\n// because the matched route is stored in the request context which is cleared\n// after the handler returns.\nfunc CurrentRoute(r *http.Request) *Route {\n\tif rv := r.Context().Value(routeKey); rv != nil {\n\t\treturn rv.(*Route)\n\t}\n\treturn nil\n}\n\nfunc requestWithVars(r *http.Request, vars map[string]string) *http.Request {\n\tctx := context.WithValue(r.Context(), varsKey, vars)\n\treturn r.WithContext(ctx)\n}\n\nfunc requestWithRoute(r *http.Request, route *Route) *http.Request {\n\tctx := context.WithValue(r.Context(), routeKey, route)\n\treturn r.WithContext(ctx)\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n// cleanPath returns the canonical path for p, eliminating . and .. elements.\n// Borrowed from the net/http package.\nfunc cleanPath(p string) string {\n\tif p == \"\" {\n\t\treturn \"/\"\n\t}\n\tif p[0] != '/' {\n\t\tp = \"/\" + p\n\t}\n\tnp := path.Clean(p)\n\t// path.Clean removes trailing slash except for root;\n\t// put the trailing slash back if necessary.\n\tif p[len(p)-1] == '/' && np != \"/\" {\n\t\tnp += \"/\"\n\t}\n\n\treturn np\n}\n\n// uniqueVars returns an error if two slices contain duplicated strings.\nfunc uniqueVars(s1, s2 []string) error {\n\tfor _, v1 := range s1 {\n\t\tfor _, v2 := range s2 {\n\t\t\tif v1 == v2 {\n\t\t\t\treturn fmt.Errorf(\"mux: duplicated route variable %q\", v2)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// checkPairs returns the count of strings passed in, and an error if\n// the count is not an even number.\nfunc checkPairs(pairs ...string) (int, error) {\n\tlength := len(pairs)\n\tif length%2 != 0 {\n\t\treturn length, fmt.Errorf(\n\t\t\t\"mux: number of parameters must be multiple of 2, got %v\", pairs)\n\t}\n\treturn length, nil\n}\n\n// mapFromPairsToString converts variadic string parameters to a\n// string to string map.\nfunc mapFromPairsToString(pairs ...string) (map[string]string, error) {\n\tlength, err := checkPairs(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm := make(map[string]string, length/2)\n\tfor i := 0; i < length; i += 2 {\n\t\tm[pairs[i]] = pairs[i+1]\n\t}\n\treturn m, nil\n}\n\n// mapFromPairsToRegex converts variadic string parameters to a\n// string to regex map.\nfunc mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {\n\tlength, err := checkPairs(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm := make(map[string]*regexp.Regexp, length/2)\n\tfor i := 0; i < length; i += 2 {\n\t\tregex, err := regexp.Compile(pairs[i+1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tm[pairs[i]] = regex\n\t}\n\treturn m, nil\n}\n\n// matchInArray returns true if the given string value is in the array.\nfunc matchInArray(arr []string, value string) bool {\n\tfor _, v := range arr {\n\t\tif v == value {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// matchMapWithString returns true if the given key/value pairs exist in a given map.\nfunc matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool {\n\tfor k, v := range toCheck {\n\t\t// Check if key exists.\n\t\tif canonicalKey {\n\t\t\tk = http.CanonicalHeaderKey(k)\n\t\t}\n\t\tif values := toMatch[k]; values == nil {\n\t\t\treturn false\n\t\t} else if v != \"\" {\n\t\t\t// If value was defined as an empty string we only check that the\n\t\t\t// key exists. Otherwise we also check for equality.\n\t\t\tvalueExists := false\n\t\t\tfor _, value := range values {\n\t\t\t\tif v == value {\n\t\t\t\t\tvalueExists = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !valueExists {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\n// matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against\n// the given regex\nfunc matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool {\n\tfor k, v := range toCheck {\n\t\t// Check if key exists.\n\t\tif canonicalKey {\n\t\t\tk = http.CanonicalHeaderKey(k)\n\t\t}\n\t\tif values := toMatch[k]; values == nil {\n\t\t\treturn false\n\t\t} else if v != nil {\n\t\t\t// If value was defined as an empty string we only check that the\n\t\t\t// key exists. Otherwise we also check for equality.\n\t\t\tvalueExists := false\n\t\t\tfor _, value := range values {\n\t\t\t\tif v.MatchString(value) {\n\t\t\t\t\tvalueExists = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !valueExists {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\n// methodNotAllowed replies to the request with an HTTP status code 405.\nfunc methodNotAllowed(w http.ResponseWriter, r *http.Request) {\n\tw.WriteHeader(http.StatusMethodNotAllowed)\n}\n\n// methodNotAllowedHandler returns a simple request handler\n// that replies to each request with a status code 405.\nfunc methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) }\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/regexp.go",
    "content": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mux\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype routeRegexpOptions struct {\n\tstrictSlash    bool\n\tuseEncodedPath bool\n}\n\ntype regexpType int\n\nconst (\n\tregexpTypePath regexpType = iota\n\tregexpTypeHost\n\tregexpTypePrefix\n\tregexpTypeQuery\n)\n\n// newRouteRegexp parses a route template and returns a routeRegexp,\n// used to match a host, a path or a query string.\n//\n// It will extract named variables, assemble a regexp to be matched, create\n// a \"reverse\" template to build URLs and compile regexps to validate variable\n// values used in URL building.\n//\n// Previously we accepted only Python-like identifiers for variable\n// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that\n// name and pattern can't be empty, and names can't contain a colon.\nfunc newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) {\n\t// Check if it is well-formed.\n\tidxs, errBraces := braceIndices(tpl)\n\tif errBraces != nil {\n\t\treturn nil, errBraces\n\t}\n\t// Backup the original.\n\ttemplate := tpl\n\t// Now let's parse it.\n\tdefaultPattern := \"[^/]+\"\n\tif typ == regexpTypeQuery {\n\t\tdefaultPattern = \".*\"\n\t} else if typ == regexpTypeHost {\n\t\tdefaultPattern = \"[^.]+\"\n\t}\n\t// Only match strict slash if not matching\n\tif typ != regexpTypePath {\n\t\toptions.strictSlash = false\n\t}\n\t// Set a flag for strictSlash.\n\tendSlash := false\n\tif options.strictSlash && strings.HasSuffix(tpl, \"/\") {\n\t\ttpl = tpl[:len(tpl)-1]\n\t\tendSlash = true\n\t}\n\tvarsN := make([]string, len(idxs)/2)\n\tvarsR := make([]*regexp.Regexp, len(idxs)/2)\n\tpattern := bytes.NewBufferString(\"\")\n\tpattern.WriteByte('^')\n\treverse := bytes.NewBufferString(\"\")\n\tvar end int\n\tvar err error\n\tfor i := 0; i < len(idxs); i += 2 {\n\t\t// Set all values we are interested in.\n\t\traw := tpl[end:idxs[i]]\n\t\tend = idxs[i+1]\n\t\tparts := strings.SplitN(tpl[idxs[i]+1:end-1], \":\", 2)\n\t\tname := parts[0]\n\t\tpatt := defaultPattern\n\t\tif len(parts) == 2 {\n\t\t\tpatt = parts[1]\n\t\t}\n\t\t// Name or pattern can't be empty.\n\t\tif name == \"\" || patt == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"mux: missing name or pattern in %q\",\n\t\t\t\ttpl[idxs[i]:end])\n\t\t}\n\t\t// Build the regexp pattern.\n\t\tfmt.Fprintf(pattern, \"%s(?P<%s>%s)\", regexp.QuoteMeta(raw), varGroupName(i/2), patt)\n\n\t\t// Build the reverse template.\n\t\tfmt.Fprintf(reverse, \"%s%%s\", raw)\n\n\t\t// Append variable name and compiled pattern.\n\t\tvarsN[i/2] = name\n\t\tvarsR[i/2], err = regexp.Compile(fmt.Sprintf(\"^%s$\", patt))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\t// Add the remaining.\n\traw := tpl[end:]\n\tpattern.WriteString(regexp.QuoteMeta(raw))\n\tif options.strictSlash {\n\t\tpattern.WriteString(\"[/]?\")\n\t}\n\tif typ == regexpTypeQuery {\n\t\t// Add the default pattern if the query value is empty\n\t\tif queryVal := strings.SplitN(template, \"=\", 2)[1]; queryVal == \"\" {\n\t\t\tpattern.WriteString(defaultPattern)\n\t\t}\n\t}\n\tif typ != regexpTypePrefix {\n\t\tpattern.WriteByte('$')\n\t}\n\n\tvar wildcardHostPort bool\n\tif typ == regexpTypeHost {\n\t\tif !strings.Contains(pattern.String(), \":\") {\n\t\t\twildcardHostPort = true\n\t\t}\n\t}\n\treverse.WriteString(raw)\n\tif endSlash {\n\t\treverse.WriteByte('/')\n\t}\n\t// Compile full regexp.\n\treg, errCompile := regexp.Compile(pattern.String())\n\tif errCompile != nil {\n\t\treturn nil, errCompile\n\t}\n\n\t// Check for capturing groups which used to work in older versions\n\tif reg.NumSubexp() != len(idxs)/2 {\n\t\tpanic(fmt.Sprintf(\"route %s contains capture groups in its regexp. \", template) +\n\t\t\t\"Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)\")\n\t}\n\n\t// Done!\n\treturn &routeRegexp{\n\t\ttemplate:         template,\n\t\tregexpType:       typ,\n\t\toptions:          options,\n\t\tregexp:           reg,\n\t\treverse:          reverse.String(),\n\t\tvarsN:            varsN,\n\t\tvarsR:            varsR,\n\t\twildcardHostPort: wildcardHostPort,\n\t}, nil\n}\n\n// routeRegexp stores a regexp to match a host or path and information to\n// collect and validate route variables.\ntype routeRegexp struct {\n\t// The unmodified template.\n\ttemplate string\n\t// The type of match\n\tregexpType regexpType\n\t// Options for matching\n\toptions routeRegexpOptions\n\t// Expanded regexp.\n\tregexp *regexp.Regexp\n\t// Reverse template.\n\treverse string\n\t// Variable names.\n\tvarsN []string\n\t// Variable regexps (validators).\n\tvarsR []*regexp.Regexp\n\t// Wildcard host-port (no strict port match in hostname)\n\twildcardHostPort bool\n}\n\n// Match matches the regexp against the URL host or path.\nfunc (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {\n\tif r.regexpType == regexpTypeHost {\n\t\thost := getHost(req)\n\t\tif r.wildcardHostPort {\n\t\t\t// Don't be strict on the port match\n\t\t\tif i := strings.Index(host, \":\"); i != -1 {\n\t\t\t\thost = host[:i]\n\t\t\t}\n\t\t}\n\t\treturn r.regexp.MatchString(host)\n\t}\n\n\tif r.regexpType == regexpTypeQuery {\n\t\treturn r.matchQueryString(req)\n\t}\n\tpath := req.URL.Path\n\tif r.options.useEncodedPath {\n\t\tpath = req.URL.EscapedPath()\n\t}\n\treturn r.regexp.MatchString(path)\n}\n\n// url builds a URL part using the given values.\nfunc (r *routeRegexp) url(values map[string]string) (string, error) {\n\turlValues := make([]interface{}, len(r.varsN))\n\tfor k, v := range r.varsN {\n\t\tvalue, ok := values[v]\n\t\tif !ok {\n\t\t\treturn \"\", fmt.Errorf(\"mux: missing route variable %q\", v)\n\t\t}\n\t\tif r.regexpType == regexpTypeQuery {\n\t\t\tvalue = url.QueryEscape(value)\n\t\t}\n\t\turlValues[k] = value\n\t}\n\trv := fmt.Sprintf(r.reverse, urlValues...)\n\tif !r.regexp.MatchString(rv) {\n\t\t// The URL is checked against the full regexp, instead of checking\n\t\t// individual variables. This is faster but to provide a good error\n\t\t// message, we check individual regexps if the URL doesn't match.\n\t\tfor k, v := range r.varsN {\n\t\t\tif !r.varsR[k].MatchString(values[v]) {\n\t\t\t\treturn \"\", fmt.Errorf(\n\t\t\t\t\t\"mux: variable %q doesn't match, expected %q\", values[v],\n\t\t\t\t\tr.varsR[k].String())\n\t\t\t}\n\t\t}\n\t}\n\treturn rv, nil\n}\n\n// getURLQuery returns a single query parameter from a request URL.\n// For a URL with foo=bar&baz=ding, we return only the relevant key\n// value pair for the routeRegexp.\nfunc (r *routeRegexp) getURLQuery(req *http.Request) string {\n\tif r.regexpType != regexpTypeQuery {\n\t\treturn \"\"\n\t}\n\ttemplateKey := strings.SplitN(r.template, \"=\", 2)[0]\n\tval, ok := findFirstQueryKey(req.URL.RawQuery, templateKey)\n\tif ok {\n\t\treturn templateKey + \"=\" + val\n\t}\n\treturn \"\"\n}\n\n// findFirstQueryKey returns the same result as (*url.URL).Query()[key][0].\n// If key was not found, empty string and false is returned.\nfunc findFirstQueryKey(rawQuery, key string) (value string, ok bool) {\n\tquery := []byte(rawQuery)\n\tfor len(query) > 0 {\n\t\tfoundKey := query\n\t\tif i := bytes.IndexAny(foundKey, \"&;\"); i >= 0 {\n\t\t\tfoundKey, query = foundKey[:i], foundKey[i+1:]\n\t\t} else {\n\t\t\tquery = query[:0]\n\t\t}\n\t\tif len(foundKey) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tvar value []byte\n\t\tif i := bytes.IndexByte(foundKey, '='); i >= 0 {\n\t\t\tfoundKey, value = foundKey[:i], foundKey[i+1:]\n\t\t}\n\t\tif len(foundKey) < len(key) {\n\t\t\t// Cannot possibly be key.\n\t\t\tcontinue\n\t\t}\n\t\tkeyString, err := url.QueryUnescape(string(foundKey))\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif keyString != key {\n\t\t\tcontinue\n\t\t}\n\t\tvalueString, err := url.QueryUnescape(string(value))\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\treturn valueString, true\n\t}\n\treturn \"\", false\n}\n\nfunc (r *routeRegexp) matchQueryString(req *http.Request) bool {\n\treturn r.regexp.MatchString(r.getURLQuery(req))\n}\n\n// braceIndices returns the first level curly brace indices from a string.\n// It returns an error in case of unbalanced braces.\nfunc braceIndices(s string) ([]int, error) {\n\tvar level, idx int\n\tvar idxs []int\n\tfor i := 0; i < len(s); i++ {\n\t\tswitch s[i] {\n\t\tcase '{':\n\t\t\tif level++; level == 1 {\n\t\t\t\tidx = i\n\t\t\t}\n\t\tcase '}':\n\t\t\tif level--; level == 0 {\n\t\t\t\tidxs = append(idxs, idx, i+1)\n\t\t\t} else if level < 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"mux: unbalanced braces in %q\", s)\n\t\t\t}\n\t\t}\n\t}\n\tif level != 0 {\n\t\treturn nil, fmt.Errorf(\"mux: unbalanced braces in %q\", s)\n\t}\n\treturn idxs, nil\n}\n\n// varGroupName builds a capturing group name for the indexed variable.\nfunc varGroupName(idx int) string {\n\treturn \"v\" + strconv.Itoa(idx)\n}\n\n// ----------------------------------------------------------------------------\n// routeRegexpGroup\n// ----------------------------------------------------------------------------\n\n// routeRegexpGroup groups the route matchers that carry variables.\ntype routeRegexpGroup struct {\n\thost    *routeRegexp\n\tpath    *routeRegexp\n\tqueries []*routeRegexp\n}\n\n// setMatch extracts the variables from the URL once a route matches.\nfunc (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {\n\t// Store host variables.\n\tif v.host != nil {\n\t\thost := getHost(req)\n\t\tif v.host.wildcardHostPort {\n\t\t\t// Don't be strict on the port match\n\t\t\tif i := strings.Index(host, \":\"); i != -1 {\n\t\t\t\thost = host[:i]\n\t\t\t}\n\t\t}\n\t\tmatches := v.host.regexp.FindStringSubmatchIndex(host)\n\t\tif len(matches) > 0 {\n\t\t\textractVars(host, matches, v.host.varsN, m.Vars)\n\t\t}\n\t}\n\tpath := req.URL.Path\n\tif r.useEncodedPath {\n\t\tpath = req.URL.EscapedPath()\n\t}\n\t// Store path variables.\n\tif v.path != nil {\n\t\tmatches := v.path.regexp.FindStringSubmatchIndex(path)\n\t\tif len(matches) > 0 {\n\t\t\textractVars(path, matches, v.path.varsN, m.Vars)\n\t\t\t// Check if we should redirect.\n\t\t\tif v.path.options.strictSlash {\n\t\t\t\tp1 := strings.HasSuffix(path, \"/\")\n\t\t\t\tp2 := strings.HasSuffix(v.path.template, \"/\")\n\t\t\t\tif p1 != p2 {\n\t\t\t\t\tu, _ := url.Parse(req.URL.String())\n\t\t\t\t\tif p1 {\n\t\t\t\t\t\tu.Path = u.Path[:len(u.Path)-1]\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.Path += \"/\"\n\t\t\t\t\t}\n\t\t\t\t\tm.Handler = http.RedirectHandler(u.String(), http.StatusMovedPermanently)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Store query string variables.\n\tfor _, q := range v.queries {\n\t\tqueryURL := q.getURLQuery(req)\n\t\tmatches := q.regexp.FindStringSubmatchIndex(queryURL)\n\t\tif len(matches) > 0 {\n\t\t\textractVars(queryURL, matches, q.varsN, m.Vars)\n\t\t}\n\t}\n}\n\n// getHost tries its best to return the request host.\n// According to section 14.23 of RFC 2616 the Host header\n// can include the port number if the default value of 80 is not used.\nfunc getHost(r *http.Request) string {\n\tif r.URL.IsAbs() {\n\t\treturn r.URL.Host\n\t}\n\treturn r.Host\n}\n\nfunc extractVars(input string, matches []int, names []string, output map[string]string) {\n\tfor i, name := range names {\n\t\toutput[name] = input[matches[2*i+2]:matches[2*i+3]]\n\t}\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/route.go",
    "content": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mux\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// Route stores information to match a request and build URLs.\ntype Route struct {\n\t// Request handler for the route.\n\thandler http.Handler\n\t// If true, this route never matches: it is only used to build URLs.\n\tbuildOnly bool\n\t// The name used to build URLs.\n\tname string\n\t// Error resulted from building a route.\n\terr error\n\n\t// \"global\" reference to all named routes\n\tnamedRoutes map[string]*Route\n\n\t// config possibly passed in from `Router`\n\trouteConf\n}\n\n// SkipClean reports whether path cleaning is enabled for this route via\n// Router.SkipClean.\nfunc (r *Route) SkipClean() bool {\n\treturn r.skipClean\n}\n\n// Match matches the route against the request.\nfunc (r *Route) Match(req *http.Request, match *RouteMatch) bool {\n\tif r.buildOnly || r.err != nil {\n\t\treturn false\n\t}\n\n\tvar matchErr error\n\n\t// Match everything.\n\tfor _, m := range r.matchers {\n\t\tif matched := m.Match(req, match); !matched {\n\t\t\tif _, ok := m.(methodMatcher); ok {\n\t\t\t\tmatchErr = ErrMethodMismatch\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Ignore ErrNotFound errors. These errors arise from match call\n\t\t\t// to Subrouters.\n\t\t\t//\n\t\t\t// This prevents subsequent matching subrouters from failing to\n\t\t\t// run middleware. If not ignored, the middleware would see a\n\t\t\t// non-nil MatchErr and be skipped, even when there was a\n\t\t\t// matching route.\n\t\t\tif match.MatchErr == ErrNotFound {\n\t\t\t\tmatch.MatchErr = nil\n\t\t\t}\n\n\t\t\tmatchErr = nil // nolint:ineffassign\n\t\t\treturn false\n\t\t} else {\n\t\t\t// Multiple routes may share the same path but use different HTTP methods. For instance:\n\t\t\t// Route 1: POST \"/users/{id}\".\n\t\t\t// Route 2: GET \"/users/{id}\", parameters: \"id\": \"[0-9]+\".\n\t\t\t//\n\t\t\t// The router must handle these cases correctly. For a GET request to \"/users/abc\" with \"id\" as \"-2\",\n\t\t\t// The router should return a \"Not Found\" error as no route fully matches this request.\n\t\t\tif match.MatchErr == ErrMethodMismatch {\n\t\t\t\tmatch.MatchErr = nil\n\t\t\t}\n\t\t}\n\t}\n\n\tif matchErr != nil {\n\t\tmatch.MatchErr = matchErr\n\t\treturn false\n\t}\n\n\tif match.MatchErr == ErrMethodMismatch && r.handler != nil {\n\t\t// We found a route which matches request method, clear MatchErr\n\t\tmatch.MatchErr = nil\n\t\t// Then override the mis-matched handler\n\t\tmatch.Handler = r.handler\n\t}\n\n\t// Yay, we have a match. Let's collect some info about it.\n\tif match.Route == nil {\n\t\tmatch.Route = r\n\t}\n\tif match.Handler == nil {\n\t\tmatch.Handler = r.handler\n\t}\n\tif match.Vars == nil {\n\t\tmatch.Vars = make(map[string]string)\n\t}\n\n\t// Set variables.\n\tr.regexp.setMatch(req, match, r)\n\treturn true\n}\n\n// ----------------------------------------------------------------------------\n// Route attributes\n// ----------------------------------------------------------------------------\n\n// GetError returns an error resulted from building the route, if any.\nfunc (r *Route) GetError() error {\n\treturn r.err\n}\n\n// BuildOnly sets the route to never match: it is only used to build URLs.\nfunc (r *Route) BuildOnly() *Route {\n\tr.buildOnly = true\n\treturn r\n}\n\n// Handler --------------------------------------------------------------------\n\n// Handler sets a handler for the route.\nfunc (r *Route) Handler(handler http.Handler) *Route {\n\tif r.err == nil {\n\t\tr.handler = handler\n\t}\n\treturn r\n}\n\n// HandlerFunc sets a handler function for the route.\nfunc (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route {\n\treturn r.Handler(http.HandlerFunc(f))\n}\n\n// GetHandler returns the handler for the route, if any.\nfunc (r *Route) GetHandler() http.Handler {\n\treturn r.handler\n}\n\n// Name -----------------------------------------------------------------------\n\n// Name sets the name for the route, used to build URLs.\n// It is an error to call Name more than once on a route.\nfunc (r *Route) Name(name string) *Route {\n\tif r.name != \"\" {\n\t\tr.err = fmt.Errorf(\"mux: route already has name %q, can't set %q\",\n\t\t\tr.name, name)\n\t}\n\tif r.err == nil {\n\t\tr.name = name\n\t\tr.namedRoutes[name] = r\n\t}\n\treturn r\n}\n\n// GetName returns the name for the route, if any.\nfunc (r *Route) GetName() string {\n\treturn r.name\n}\n\n// ----------------------------------------------------------------------------\n// Matchers\n// ----------------------------------------------------------------------------\n\n// matcher types try to match a request.\ntype matcher interface {\n\tMatch(*http.Request, *RouteMatch) bool\n}\n\n// addMatcher adds a matcher to the route.\nfunc (r *Route) addMatcher(m matcher) *Route {\n\tif r.err == nil {\n\t\tr.matchers = append(r.matchers, m)\n\t}\n\treturn r\n}\n\n// addRegexpMatcher adds a host or path matcher and builder to a route.\nfunc (r *Route) addRegexpMatcher(tpl string, typ regexpType) error {\n\tif r.err != nil {\n\t\treturn r.err\n\t}\n\tif typ == regexpTypePath || typ == regexpTypePrefix {\n\t\tif len(tpl) > 0 && tpl[0] != '/' {\n\t\t\treturn fmt.Errorf(\"mux: path must start with a slash, got %q\", tpl)\n\t\t}\n\t\tif r.regexp.path != nil {\n\t\t\ttpl = strings.TrimRight(r.regexp.path.template, \"/\") + tpl\n\t\t}\n\t}\n\trr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{\n\t\tstrictSlash:    r.strictSlash,\n\t\tuseEncodedPath: r.useEncodedPath,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, q := range r.regexp.queries {\n\t\tif err = uniqueVars(rr.varsN, q.varsN); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif typ == regexpTypeHost {\n\t\tif r.regexp.path != nil {\n\t\t\tif err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tr.regexp.host = rr\n\t} else {\n\t\tif r.regexp.host != nil {\n\t\t\tif err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif typ == regexpTypeQuery {\n\t\t\tr.regexp.queries = append(r.regexp.queries, rr)\n\t\t} else {\n\t\t\tr.regexp.path = rr\n\t\t}\n\t}\n\tr.addMatcher(rr)\n\treturn nil\n}\n\n// Headers --------------------------------------------------------------------\n\n// headerMatcher matches the request against header values.\ntype headerMatcher map[string]string\n\nfunc (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {\n\treturn matchMapWithString(m, r.Header, true)\n}\n\n// Headers adds a matcher for request header values.\n// It accepts a sequence of key/value pairs to be matched. For example:\n//\n//\tr := mux.NewRouter().NewRoute()\n//\tr.Headers(\"Content-Type\", \"application/json\",\n//\t          \"X-Requested-With\", \"XMLHttpRequest\")\n//\n// The above route will only match if both request header values match.\n// If the value is an empty string, it will match any value if the key is set.\nfunc (r *Route) Headers(pairs ...string) *Route {\n\tif r.err == nil {\n\t\tvar headers map[string]string\n\t\theaders, r.err = mapFromPairsToString(pairs...)\n\t\treturn r.addMatcher(headerMatcher(headers))\n\t}\n\treturn r\n}\n\n// headerRegexMatcher matches the request against the route given a regex for the header\ntype headerRegexMatcher map[string]*regexp.Regexp\n\nfunc (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool {\n\treturn matchMapWithRegex(m, r.Header, true)\n}\n\n// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex\n// support. For example:\n//\n//\tr := mux.NewRouter().NewRoute()\n//\tr.HeadersRegexp(\"Content-Type\", \"application/(text|json)\",\n//\t          \"X-Requested-With\", \"XMLHttpRequest\")\n//\n// The above route will only match if both the request header matches both regular expressions.\n// If the value is an empty string, it will match any value if the key is set.\n// Use the start and end of string anchors (^ and $) to match an exact value.\nfunc (r *Route) HeadersRegexp(pairs ...string) *Route {\n\tif r.err == nil {\n\t\tvar headers map[string]*regexp.Regexp\n\t\theaders, r.err = mapFromPairsToRegex(pairs...)\n\t\treturn r.addMatcher(headerRegexMatcher(headers))\n\t}\n\treturn r\n}\n\n// Host -----------------------------------------------------------------------\n\n// Host adds a matcher for the URL host.\n// It accepts a template with zero or more URL variables enclosed by {}.\n// Variables can define an optional regexp pattern to be matched:\n//\n// - {name} matches anything until the next dot.\n//\n// - {name:pattern} matches the given regexp pattern.\n//\n// For example:\n//\n//\tr := mux.NewRouter().NewRoute()\n//\tr.Host(\"www.example.com\")\n//\tr.Host(\"{subdomain}.domain.com\")\n//\tr.Host(\"{subdomain:[a-z]+}.domain.com\")\n//\n// Variable names must be unique in a given route. They can be retrieved\n// calling mux.Vars(request).\nfunc (r *Route) Host(tpl string) *Route {\n\tr.err = r.addRegexpMatcher(tpl, regexpTypeHost)\n\treturn r\n}\n\n// MatcherFunc ----------------------------------------------------------------\n\n// MatcherFunc is the function signature used by custom matchers.\ntype MatcherFunc func(*http.Request, *RouteMatch) bool\n\n// Match returns the match for a given request.\nfunc (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool {\n\treturn m(r, match)\n}\n\n// MatcherFunc adds a custom function to be used as request matcher.\nfunc (r *Route) MatcherFunc(f MatcherFunc) *Route {\n\treturn r.addMatcher(f)\n}\n\n// Methods --------------------------------------------------------------------\n\n// methodMatcher matches the request against HTTP methods.\ntype methodMatcher []string\n\nfunc (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool {\n\treturn matchInArray(m, r.Method)\n}\n\n// Methods adds a matcher for HTTP methods.\n// It accepts a sequence of one or more methods to be matched, e.g.:\n// \"GET\", \"POST\", \"PUT\".\nfunc (r *Route) Methods(methods ...string) *Route {\n\tfor k, v := range methods {\n\t\tmethods[k] = strings.ToUpper(v)\n\t}\n\treturn r.addMatcher(methodMatcher(methods))\n}\n\n// Path -----------------------------------------------------------------------\n\n// Path adds a matcher for the URL path.\n// It accepts a template with zero or more URL variables enclosed by {}. The\n// template must start with a \"/\".\n// Variables can define an optional regexp pattern to be matched:\n//\n// - {name} matches anything until the next slash.\n//\n// - {name:pattern} matches the given regexp pattern.\n//\n// For example:\n//\n//\tr := mux.NewRouter().NewRoute()\n//\tr.Path(\"/products/\").Handler(ProductsHandler)\n//\tr.Path(\"/products/{key}\").Handler(ProductsHandler)\n//\tr.Path(\"/articles/{category}/{id:[0-9]+}\").\n//\t  Handler(ArticleHandler)\n//\n// Variable names must be unique in a given route. They can be retrieved\n// calling mux.Vars(request).\nfunc (r *Route) Path(tpl string) *Route {\n\tr.err = r.addRegexpMatcher(tpl, regexpTypePath)\n\treturn r\n}\n\n// PathPrefix -----------------------------------------------------------------\n\n// PathPrefix adds a matcher for the URL path prefix. This matches if the given\n// template is a prefix of the full URL path. See Route.Path() for details on\n// the tpl argument.\n//\n// Note that it does not treat slashes specially (\"/foobar/\" will be matched by\n// the prefix \"/foo\") so you may want to use a trailing slash here.\n//\n// Also note that the setting of Router.StrictSlash() has no effect on routes\n// with a PathPrefix matcher.\nfunc (r *Route) PathPrefix(tpl string) *Route {\n\tr.err = r.addRegexpMatcher(tpl, regexpTypePrefix)\n\treturn r\n}\n\n// Query ----------------------------------------------------------------------\n\n// Queries adds a matcher for URL query values.\n// It accepts a sequence of key/value pairs. Values may define variables.\n// For example:\n//\n//\tr := mux.NewRouter().NewRoute()\n//\tr.Queries(\"foo\", \"bar\", \"id\", \"{id:[0-9]+}\")\n//\n// The above route will only match if the URL contains the defined queries\n// values, e.g.: ?foo=bar&id=42.\n//\n// If the value is an empty string, it will match any value if the key is set.\n//\n// Variables can define an optional regexp pattern to be matched:\n//\n// - {name} matches anything until the next slash.\n//\n// - {name:pattern} matches the given regexp pattern.\nfunc (r *Route) Queries(pairs ...string) *Route {\n\tlength := len(pairs)\n\tif length%2 != 0 {\n\t\tr.err = fmt.Errorf(\n\t\t\t\"mux: number of parameters must be multiple of 2, got %v\", pairs)\n\t\treturn nil\n\t}\n\tfor i := 0; i < length; i += 2 {\n\t\tif r.err = r.addRegexpMatcher(pairs[i]+\"=\"+pairs[i+1], regexpTypeQuery); r.err != nil {\n\t\t\treturn r\n\t\t}\n\t}\n\n\treturn r\n}\n\n// Schemes --------------------------------------------------------------------\n\n// schemeMatcher matches the request against URL schemes.\ntype schemeMatcher []string\n\nfunc (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool {\n\tscheme := r.URL.Scheme\n\t// https://golang.org/pkg/net/http/#Request\n\t// \"For [most] server requests, fields other than Path and RawQuery will be\n\t// empty.\"\n\t// Since we're an http muxer, the scheme is either going to be http or https\n\t// though, so we can just set it based on the tls termination state.\n\tif scheme == \"\" {\n\t\tif r.TLS == nil {\n\t\t\tscheme = \"http\"\n\t\t} else {\n\t\t\tscheme = \"https\"\n\t\t}\n\t}\n\treturn matchInArray(m, scheme)\n}\n\n// Schemes adds a matcher for URL schemes.\n// It accepts a sequence of schemes to be matched, e.g.: \"http\", \"https\".\n// If the request's URL has a scheme set, it will be matched against.\n// Generally, the URL scheme will only be set if a previous handler set it,\n// such as the ProxyHeaders handler from gorilla/handlers.\n// If unset, the scheme will be determined based on the request's TLS\n// termination state.\n// The first argument to Schemes will be used when constructing a route URL.\nfunc (r *Route) Schemes(schemes ...string) *Route {\n\tfor k, v := range schemes {\n\t\tschemes[k] = strings.ToLower(v)\n\t}\n\tif len(schemes) > 0 {\n\t\tr.buildScheme = schemes[0]\n\t}\n\treturn r.addMatcher(schemeMatcher(schemes))\n}\n\n// BuildVarsFunc --------------------------------------------------------------\n\n// BuildVarsFunc is the function signature used by custom build variable\n// functions (which can modify route variables before a route's URL is built).\ntype BuildVarsFunc func(map[string]string) map[string]string\n\n// BuildVarsFunc adds a custom function to be used to modify build variables\n// before a route's URL is built.\nfunc (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {\n\tif r.buildVarsFunc != nil {\n\t\t// compose the old and new functions\n\t\told := r.buildVarsFunc\n\t\tr.buildVarsFunc = func(m map[string]string) map[string]string {\n\t\t\treturn f(old(m))\n\t\t}\n\t} else {\n\t\tr.buildVarsFunc = f\n\t}\n\treturn r\n}\n\n// Subrouter ------------------------------------------------------------------\n\n// Subrouter creates a subrouter for the route.\n//\n// It will test the inner routes only if the parent route matched. For example:\n//\n//\tr := mux.NewRouter().NewRoute()\n//\ts := r.Host(\"www.example.com\").Subrouter()\n//\ts.HandleFunc(\"/products/\", ProductsHandler)\n//\ts.HandleFunc(\"/products/{key}\", ProductHandler)\n//\ts.HandleFunc(\"/articles/{category}/{id:[0-9]+}\"), ArticleHandler)\n//\n// Here, the routes registered in the subrouter won't be tested if the host\n// doesn't match.\nfunc (r *Route) Subrouter() *Router {\n\t// initialize a subrouter with a copy of the parent route's configuration\n\trouter := &Router{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}\n\tr.addMatcher(router)\n\treturn router\n}\n\n// ----------------------------------------------------------------------------\n// URL building\n// ----------------------------------------------------------------------------\n\n// URL builds a URL for the route.\n//\n// It accepts a sequence of key/value pairs for the route variables. For\n// example, given this route:\n//\n//\tr := mux.NewRouter()\n//\tr.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler).\n//\t  Name(\"article\")\n//\n// ...a URL for it can be built using:\n//\n//\turl, err := r.Get(\"article\").URL(\"category\", \"technology\", \"id\", \"42\")\n//\n// ...which will return an url.URL with the following path:\n//\n//\t\"/articles/technology/42\"\n//\n// This also works for host variables:\n//\n//\tr := mux.NewRouter()\n//\tr.HandleFunc(\"/articles/{category}/{id:[0-9]+}\", ArticleHandler).\n//\t  Host(\"{subdomain}.domain.com\").\n//\t  Name(\"article\")\n//\n//\t// url.String() will be \"http://news.domain.com/articles/technology/42\"\n//\turl, err := r.Get(\"article\").URL(\"subdomain\", \"news\",\n//\t                                 \"category\", \"technology\",\n//\t                                 \"id\", \"42\")\n//\n// The scheme of the resulting url will be the first argument that was passed to Schemes:\n//\n//\t// url.String() will be \"https://example.com\"\n//\tr := mux.NewRouter().NewRoute()\n//\turl, err := r.Host(\"example.com\")\n//\t             .Schemes(\"https\", \"http\").URL()\n//\n// All variables defined in the route are required, and their values must\n// conform to the corresponding patterns.\nfunc (r *Route) URL(pairs ...string) (*url.URL, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tvalues, err := r.prepareVars(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar scheme, host, path string\n\tqueries := make([]string, 0, len(r.regexp.queries))\n\tif r.regexp.host != nil {\n\t\tif host, err = r.regexp.host.url(values); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tscheme = \"http\"\n\t\tif r.buildScheme != \"\" {\n\t\t\tscheme = r.buildScheme\n\t\t}\n\t}\n\tif r.regexp.path != nil {\n\t\tif path, err = r.regexp.path.url(values); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tfor _, q := range r.regexp.queries {\n\t\tvar query string\n\t\tif query, err = q.url(values); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tqueries = append(queries, query)\n\t}\n\treturn &url.URL{\n\t\tScheme:   scheme,\n\t\tHost:     host,\n\t\tPath:     path,\n\t\tRawQuery: strings.Join(queries, \"&\"),\n\t}, nil\n}\n\n// URLHost builds the host part of the URL for a route. See Route.URL().\n//\n// The route must have a host defined.\nfunc (r *Route) URLHost(pairs ...string) (*url.URL, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tif r.regexp.host == nil {\n\t\treturn nil, errors.New(\"mux: route doesn't have a host\")\n\t}\n\tvalues, err := r.prepareVars(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thost, err := r.regexp.host.url(values)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tu := &url.URL{\n\t\tScheme: \"http\",\n\t\tHost:   host,\n\t}\n\tif r.buildScheme != \"\" {\n\t\tu.Scheme = r.buildScheme\n\t}\n\treturn u, nil\n}\n\n// URLPath builds the path part of the URL for a route. See Route.URL().\n//\n// The route must have a path defined.\nfunc (r *Route) URLPath(pairs ...string) (*url.URL, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tif r.regexp.path == nil {\n\t\treturn nil, errors.New(\"mux: route doesn't have a path\")\n\t}\n\tvalues, err := r.prepareVars(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpath, err := r.regexp.path.url(values)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &url.URL{\n\t\tPath: path,\n\t}, nil\n}\n\n// GetPathTemplate returns the template used to build the\n// route match.\n// This is useful for building simple REST API documentation and for instrumentation\n// against third-party services.\n// An error will be returned if the route does not define a path.\nfunc (r *Route) GetPathTemplate() (string, error) {\n\tif r.err != nil {\n\t\treturn \"\", r.err\n\t}\n\tif r.regexp.path == nil {\n\t\treturn \"\", errors.New(\"mux: route doesn't have a path\")\n\t}\n\treturn r.regexp.path.template, nil\n}\n\n// GetPathRegexp returns the expanded regular expression used to match route path.\n// This is useful for building simple REST API documentation and for instrumentation\n// against third-party services.\n// An error will be returned if the route does not define a path.\nfunc (r *Route) GetPathRegexp() (string, error) {\n\tif r.err != nil {\n\t\treturn \"\", r.err\n\t}\n\tif r.regexp.path == nil {\n\t\treturn \"\", errors.New(\"mux: route does not have a path\")\n\t}\n\treturn r.regexp.path.regexp.String(), nil\n}\n\n// GetQueriesRegexp returns the expanded regular expressions used to match the\n// route queries.\n// This is useful for building simple REST API documentation and for instrumentation\n// against third-party services.\n// An error will be returned if the route does not have queries.\nfunc (r *Route) GetQueriesRegexp() ([]string, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tif r.regexp.queries == nil {\n\t\treturn nil, errors.New(\"mux: route doesn't have queries\")\n\t}\n\tqueries := make([]string, 0, len(r.regexp.queries))\n\tfor _, query := range r.regexp.queries {\n\t\tqueries = append(queries, query.regexp.String())\n\t}\n\treturn queries, nil\n}\n\n// GetQueriesTemplates returns the templates used to build the\n// query matching.\n// This is useful for building simple REST API documentation and for instrumentation\n// against third-party services.\n// An error will be returned if the route does not define queries.\nfunc (r *Route) GetQueriesTemplates() ([]string, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tif r.regexp.queries == nil {\n\t\treturn nil, errors.New(\"mux: route doesn't have queries\")\n\t}\n\tqueries := make([]string, 0, len(r.regexp.queries))\n\tfor _, query := range r.regexp.queries {\n\t\tqueries = append(queries, query.template)\n\t}\n\treturn queries, nil\n}\n\n// GetMethods returns the methods the route matches against\n// This is useful for building simple REST API documentation and for instrumentation\n// against third-party services.\n// An error will be returned if route does not have methods.\nfunc (r *Route) GetMethods() ([]string, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tfor _, m := range r.matchers {\n\t\tif methods, ok := m.(methodMatcher); ok {\n\t\t\treturn []string(methods), nil\n\t\t}\n\t}\n\treturn nil, errors.New(\"mux: route doesn't have methods\")\n}\n\n// GetHostTemplate returns the template used to build the\n// route match.\n// This is useful for building simple REST API documentation and for instrumentation\n// against third-party services.\n// An error will be returned if the route does not define a host.\nfunc (r *Route) GetHostTemplate() (string, error) {\n\tif r.err != nil {\n\t\treturn \"\", r.err\n\t}\n\tif r.regexp.host == nil {\n\t\treturn \"\", errors.New(\"mux: route doesn't have a host\")\n\t}\n\treturn r.regexp.host.template, nil\n}\n\n// GetVarNames returns the names of all variables added by regexp matchers\n// These can be used to know which route variables should be passed into r.URL()\nfunc (r *Route) GetVarNames() ([]string, error) {\n\tif r.err != nil {\n\t\treturn nil, r.err\n\t}\n\tvar varNames []string\n\tif r.regexp.host != nil {\n\t\tvarNames = append(varNames, r.regexp.host.varsN...)\n\t}\n\tif r.regexp.path != nil {\n\t\tvarNames = append(varNames, r.regexp.path.varsN...)\n\t}\n\tfor _, regx := range r.regexp.queries {\n\t\tvarNames = append(varNames, regx.varsN...)\n\t}\n\treturn varNames, nil\n}\n\n// prepareVars converts the route variable pairs into a map. If the route has a\n// BuildVarsFunc, it is invoked.\nfunc (r *Route) prepareVars(pairs ...string) (map[string]string, error) {\n\tm, err := mapFromPairsToString(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn r.buildVars(m), nil\n}\n\nfunc (r *Route) buildVars(m map[string]string) map[string]string {\n\tif r.buildVarsFunc != nil {\n\t\tm = r.buildVarsFunc(m)\n\t}\n\treturn m\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/gorilla/mux/test_helpers.go",
    "content": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mux\n\nimport \"net/http\"\n\n// SetURLVars sets the URL variables for the given request, to be accessed via\n// mux.Vars for testing route behaviour. Arguments are not modified, a shallow\n// copy is returned.\n//\n// This API should only be used for testing purposes; it provides a way to\n// inject variables into the request context. Alternatively, URL variables\n// can be set by making a route that captures the required variables,\n// starting a server and sending the request to that server.\nfunc SetURLVars(r *http.Request, val map[string]string) *http.Request {\n\treturn requestWithVars(r, val)\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/pinterface/.gitignore",
    "content": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n*.test\n*.prof\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/pinterface/.travis.yml",
    "content": "language: go\n\ngo:\n  - \"1.8\"\n  - \"1.9\"\n  - \"1.10\"\n  - \"1.11\"\n  - \"1.12\"\n  - \"1.13\"\n  - \"1.14\"\n  - tip\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/pinterface/LICENSE",
    "content": "Copyright 2021 Alexander F. Rødseth\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/pinterface/README.md",
    "content": "# pinterface\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/xyproto/pinterface)](https://goreportcard.com/report/github.com/xyproto/pinterface) [![License](https://img.shields.io/badge/license-BSD-green.svg?style=flat)](https://raw.githubusercontent.com/xyproto/pinterface/main/LICENSE)\n\nInterface types for `simple*` and `permission*` packages.\n\nInterfaces for:\n---------------\n\n* Redis: [permissions2](https://github.com/xyproto/permissions2) and [simpleredis](https://github.com/xyproto/simpleredis)\n* Bolt: [permissionbolt](https://github.com/xyproto/permissionbolt) and [simplebolt](https://github.com/xyproto/simplebolt)\n* MariaDB/MySQL: [permissionsql](https://github.com/xyproto/permissionsql) and [simplemaria](https://github.com/xyproto/simplemaria)\n* PostgreSQL: [pstore](https://github.com/xyproto/pstore) and [simplehstore](https://github.com/xyproto/simplehstore)\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/go:github-xyproto-pinterface.svg)](https://repology.org/project/go:github-xyproto-pinterface/versions)\n\nGeneral information\n-------------------\n\n* Version: 1.5.3 (The tag is `v1.5.3` to work better with `go mod`. The API has version `5.3`.)\n* License: BSD-3\n* Author: Alexander F. Rødseth &lt;xyproto@archlinux.org&gt;\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/pinterface/pinterface.go",
    "content": "// Package pinterface provides interface types for the xyproto/simple* and xyproto/permission* packages\npackage pinterface\n\nimport \"net/http\"\n\n// Version is the API version. The API is stable within the same major version number\nconst Version = 5.3\n\n// Database interfaces\n\ntype IList interface {\n\tAdd(value string) error\n\tAll() ([]string, error)\n\tClear() error\n\tLastN(n int) ([]string, error)\n\tLast() (string, error)\n\tRemove() error\n}\n\ntype ISet interface {\n\tAdd(value string) error\n\tAll() ([]string, error)\n\tClear() error\n\tDel(value string) error\n\tHas(value string) (bool, error)\n\tRemove() error\n}\n\ntype IHashMap interface {\n\tAll() ([]string, error)\n\tClear() error\n\tDelKey(owner, key string) error\n\tDel(key string) error\n\tExists(owner string) (bool, error)\n\tGet(owner, key string) (string, error)\n\tHas(owner, key string) (bool, error)\n\tKeys(owner string) ([]string, error)\n\tRemove() error\n\tSet(owner, key, value string) error\n}\n\ntype IHashMap2 interface {\n\tAll() ([]string, error)\n\tAllWhere(key, value string) ([]string, error)\n\tClear() error\n\tCount() (int64, error)\n\tDelKey(owner, key string) error\n\tDel(key string) error\n\tEmpty() (bool, error)\n\tExists(owner string) (bool, error)\n\tGetMap(owner string, keys []string) (map[string]string, error)\n\tGet(owner, key string) (string, error)\n\tHas(owner, key string) (bool, error)\n\tKeys(owner string) ([]string, error)\n\tRemove() error\n\tSetLargeMap(all map[string]map[string]string) error\n\tSetMap(owner string, m map[string]string) error\n\tSet(owner, key, value string) error\n}\n\ntype IKeyValue interface {\n\tClear() error\n\tDel(key string) error\n\tGet(key string) (string, error)\n\tInc(key string) (string, error)\n\tRemove() error\n\tSet(key, value string) error\n}\n\n// Interface for making it possible to depend on different versions of the permission package,\n// or other packages that implement userstates.\ntype IUserState interface {\n\tAddUnconfirmed(username, confirmationCode string)\n\tAddUser(username, password, email string)\n\tAdminRights(req *http.Request) bool\n\tAllUnconfirmedUsernames() ([]string, error)\n\tAllUsernames() ([]string, error)\n\tAlreadyHasConfirmationCode(confirmationCode string) bool\n\tBooleanField(username, fieldname string) bool\n\tClearCookie(w http.ResponseWriter)\n\tConfirmationCode(username string) (string, error)\n\tConfirmUserByConfirmationCode(confirmationcode string) error\n\tConfirm(username string)\n\tCookieSecret() string\n\tCookieTimeout(username string) int64\n\tCorrectPassword(username, password string) bool\n\tEmail(username string) (string, error)\n\tFindUserByConfirmationCode(confirmationcode string) (string, error)\n\tGenerateUniqueConfirmationCode() (string, error)\n\tHashPassword(username, password string) string\n\tHasUser(username string) bool\n\tIsAdmin(username string) bool\n\tIsConfirmed(username string) bool\n\tIsLoggedIn(username string) bool\n\tLogin(w http.ResponseWriter, username string) error\n\tLogout(username string)\n\tMarkConfirmed(username string)\n\tPasswordAlgo() string\n\tPasswordHash(username string) (string, error)\n\tRemoveAdminStatus(username string)\n\tRemoveUnconfirmed(username string)\n\tRemoveUser(username string)\n\tSetAdminStatus(username string)\n\tSetBooleanField(username, fieldname string, val bool)\n\tSetCookieSecret(cookieSecret string)\n\tSetCookieTimeout(cookieTime int64)\n\tSetLoggedIn(username string)\n\tSetLoggedOut(username string)\n\tSetMinimumConfirmationCodeLength(length int)\n\tSetPasswordAlgo(algorithm string) error\n\tSetPassword(username, password string)\n\tSetUsernameCookie(w http.ResponseWriter, username string) error\n\tUsernameCookie(req *http.Request) (string, error)\n\tUsername(req *http.Request) string\n\tUserRights(req *http.Request) bool\n\n\tCreator() ICreator\n\tHost() IHost\n\tUsers() IHashMap\n}\n\n// Data structure creator\ntype ICreator interface {\n\tNewHashMap(id string) (IHashMap, error)\n\tNewKeyValue(id string) (IKeyValue, error)\n\tNewList(id string) (IList, error)\n\tNewSet(id string) (ISet, error)\n}\n\n// Database host (or file)\ntype IHost interface {\n\tClose()\n\tPing() error\n}\n\n// Redis host (implemented structures can also be an IHost, of course)\ntype IRedisHost interface {\n\tDatabaseIndex()\n\tPool()\n}\n\n// Redis data structure creator\ntype IRedisCreator interface {\n\tSelectDatabase(dbindex int)\n}\n\n// Middleware for permissions\ntype IPermissions interface {\n\tAddAdminPath(prefix string)\n\tAddPublicPath(prefix string)\n\tAddUserPath(prefix string)\n\tClear()\n\tDenyFunction() http.HandlerFunc\n\tRejected(w http.ResponseWriter, req *http.Request) bool\n\tServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc)\n\tSetAdminPath(pathPrefixes []string)\n\tSetDenyFunction(f http.HandlerFunc)\n\tSetPublicPath(pathPrefixes []string)\n\tSetUserPath(pathPrefixes []string)\n\tUserState() IUserState\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/simpleredis/v2/LICENSE",
    "content": "Copyright 2023 Alexander F. Rødseth\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/simpleredis/v2/creator.go",
    "content": "package simpleredis\n\nimport (\n\t\"github.com/xyproto/pinterface\"\n)\n\n// For implementing pinterface.ICreator\n\ntype RedisCreator struct {\n\tpool    *ConnectionPool\n\tdbindex int\n}\n\nfunc NewCreator(pool *ConnectionPool, dbindex int) *RedisCreator {\n\treturn &RedisCreator{pool, dbindex}\n}\n\nfunc (c *RedisCreator) SelectDatabase(dbindex int) {\n\tc.dbindex = dbindex\n}\n\nfunc (c *RedisCreator) NewList(id string) (pinterface.IList, error) {\n\treturn &List{c.pool, id, c.dbindex}, nil\n}\n\nfunc (c *RedisCreator) NewSet(id string) (pinterface.ISet, error) {\n\treturn &Set{c.pool, id, c.dbindex}, nil\n}\n\nfunc (c *RedisCreator) NewHashMap(id string) (pinterface.IHashMap, error) {\n\treturn &HashMap{c.pool, id, c.dbindex}, nil\n}\n\nfunc (c *RedisCreator) NewKeyValue(id string) (pinterface.IKeyValue, error) {\n\treturn &KeyValue{c.pool, id, c.dbindex}, nil\n}\n"
  },
  {
    "path": "examples/web/vendor/github.com/xyproto/simpleredis/v2/simpleredis.go",
    "content": "// Package simpleredis provides an easy way to use Redis.\npackage simpleredis\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/gomodule/redigo/redis\"\n)\n\nconst (\n\t// Version number. Stable API within major version numbers.\n\tVersion = 2.6\n\n\t// The default [url]:port that Redis is running at\n\tdefaultRedisServer = \":6379\"\n)\n\n// Common for each of the Redis data structures used here\ntype redisDatastructure struct {\n\tpool    *ConnectionPool\n\tid      string\n\tdbindex int\n}\n\ntype (\n\t// A pool of readily available Redis connections\n\tConnectionPool redis.Pool\n\n\tList     redisDatastructure\n\tSet      redisDatastructure\n\tHashMap  redisDatastructure\n\tKeyValue redisDatastructure\n)\n\nvar (\n\t// Timeout settings for new connections\n\tconnectTimeout = 7 * time.Second\n\treadTimeout    = 7 * time.Second\n\twriteTimeout   = 7 * time.Second\n\tidleTimeout    = 240 * time.Second\n\n\t// How many connections should stay ready for requests, at a maximum?\n\t// When an idle connection is used, new idle connections are created.\n\tmaxIdleConnections = 3\n)\n\n/* --- Helper functions --- */\n\n// Connect to the local instance of Redis at port 6379\nfunc newRedisConnection() (redis.Conn, error) {\n\treturn newRedisConnectionTo(defaultRedisServer)\n}\n\n// Connect to host:port, host may be omitted, so \":6379\" is valid.\n// Will not try to AUTH with any given password (password@host:port).\nfunc newRedisConnectionTo(hostColonPort string) (redis.Conn, error) {\n\t// Discard the password, if provided\n\tif _, theRest, ok := twoFields(hostColonPort, \"@\"); ok {\n\t\thostColonPort = theRest\n\t}\n\thostColonPort = strings.TrimSpace(hostColonPort)\n\tc, err := redis.Dial(\"tcp\", hostColonPort, redis.DialConnectTimeout(connectTimeout), redis.DialReadTimeout(readTimeout), redis.DialWriteTimeout(writeTimeout))\n\tif err != nil {\n\t\tif c != nil {\n\t\t\tc.Close()\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// Get a string from a list of results at a given position\nfunc getString(bi []interface{}, i int) string {\n\treturn string(bi[i].([]uint8))\n}\n\n// Test if the local Redis server is up and running\nfunc TestConnection() (err error) {\n\treturn TestConnectionHost(defaultRedisServer)\n}\n\n// Test if a given Redis server at host:port is up and running.\n// Does not try to PING or AUTH.\nfunc TestConnectionHost(hostColonPort string) (err error) {\n\t// Connect to the given host:port\n\tconn, err := newRedisConnectionTo(hostColonPort)\n\tdefer func() {\n\t\tif conn != nil {\n\t\t\tconn.Close()\n\t\t}\n\t\tif r := recover(); r != nil {\n\t\t\terr = errors.New(\"Could not connect to redis server: \" + hostColonPort)\n\t\t}\n\t}()\n\treturn err\n}\n\n/* --- ConnectionPool functions --- */\n\nfunc copyPoolValues(src *redis.Pool) ConnectionPool {\n\treturn ConnectionPool{\n\t\tDial:            src.Dial,\n\t\tDialContext:     src.DialContext,\n\t\tTestOnBorrow:    src.TestOnBorrow,\n\t\tMaxIdle:         src.MaxIdle,\n\t\tMaxActive:       src.MaxActive,\n\t\tIdleTimeout:     src.IdleTimeout,\n\t\tWait:            src.Wait,\n\t\tMaxConnLifetime: src.MaxConnLifetime,\n\t}\n}\n\n// Create a new connection pool\nfunc NewConnectionPool() *ConnectionPool {\n\t// The second argument is the maximum number of idle connections\n\tredisPool := &redis.Pool{\n\t\tMaxIdle:     maxIdleConnections,\n\t\tIdleTimeout: idleTimeout,\n\t\tDial:        newRedisConnection,\n\t}\n\n\tpool := copyPoolValues(redisPool)\n\treturn &pool\n}\n\n// Split a string into two parts, given a delimiter.\n// Returns the two parts and true if it works out.\nfunc twoFields(s, delim string) (string, string, bool) {\n\tif strings.Count(s, delim) != 1 {\n\t\treturn s, \"\", false\n\t}\n\tfields := strings.Split(s, delim)\n\treturn fields[0], fields[1], true\n}\n\n// Create a new connection pool given a host:port string.\n// A password may be supplied as well, on the form \"password@host:port\".\nfunc NewConnectionPoolHost(hostColonPort string) *ConnectionPool {\n\t// Create a redis Pool\n\tredisPool := &redis.Pool{\n\t\t// Maximum number of idle connections to the redis database\n\t\tMaxIdle:     maxIdleConnections,\n\t\tIdleTimeout: idleTimeout,\n\t\t// Anonymous function for calling new RedisConnectionTo with the host:port\n\t\tDial: func() (redis.Conn, error) {\n\t\t\tconn, err := newRedisConnectionTo(hostColonPort)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// If a password is given, use it to authenticate\n\t\t\tif password, _, ok := twoFields(hostColonPort, \"@\"); ok {\n\t\t\t\tif password != \"\" {\n\t\t\t\t\tif _, err := conn.Do(\"AUTH\", password); err != nil {\n\t\t\t\t\t\tconn.Close()\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn conn, err\n\t\t},\n\t}\n\tpool := copyPoolValues(redisPool)\n\treturn &pool\n}\n\n// Set the number of maximum *idle* connections standing ready when\n// creating new connection pools. When an idle connection is used,\n// a new idle connection is created. The default is 3 and should be fine\n// for most cases.\nfunc SetMaxIdleConnections(maximum int) {\n\tmaxIdleConnections = maximum\n}\n\n// Get one of the available connections from the connection pool, given a database index\nfunc (pool *ConnectionPool) Get(dbindex int) redis.Conn {\n\tredisPool := (*redis.Pool)(pool)\n\tconn := redisPool.Get()\n\t// The default database index is 0\n\tif dbindex != 0 {\n\t\t// SELECT is not critical, ignore the return values\n\t\tconn.Do(\"SELECT\", strconv.Itoa(dbindex))\n\t}\n\treturn conn\n}\n\n// Ping the server by sending a PING command\nfunc (pool *ConnectionPool) Ping() error {\n\tredisPool := (*redis.Pool)(pool)\n\tconn := redisPool.Get()\n\t_, err := conn.Do(\"PING\")\n\treturn err\n}\n\n// Close down the connection pool\nfunc (pool *ConnectionPool) Close() {\n\tredisPool := (*redis.Pool)(pool)\n\tredisPool.Close()\n}\n\n/* --- List functions --- */\n\n// Create a new list\nfunc NewList(pool *ConnectionPool, id string) *List {\n\treturn &List{pool, id, 0}\n}\n\n// Select a different database\nfunc (rl *List) SelectDatabase(dbindex int) {\n\trl.dbindex = dbindex\n}\n\n// Returns the element at index index in the list\nfunc (rl *List) Get(index int64) (string, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tresult, err := conn.Do(\"LINDEX\", rl.id, index)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.String(result, err)\n}\n\n// Get the size of the list\nfunc (rl *List) Size() (int64, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tsize, err := conn.Do(\"LLEN\", rl.id)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.Int64(size, err)\n}\n\n// Removes and returns the first element of the list\nfunc (rl *List) PopFirst() (string, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tresult, err := conn.Do(\"LPOP\", rl.id)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.String(result, err)\n}\n\n// Removes and returns the last element of the list\nfunc (rl *List) PopLast() (string, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tresult, err := conn.Do(\"LPOP\", rl.id)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.String(result, err)\n}\n\n// Add an element to the start of the list\nfunc (rl *List) AddStart(value string) error {\n\tconn := rl.pool.Get(rl.dbindex)\n\t_, err := conn.Do(\"RPUSH\", rl.id, value)\n\treturn err\n}\n\n// Add an element to the end of the list list\nfunc (rl *List) AddEnd(value string) error {\n\tconn := rl.pool.Get(rl.dbindex)\n\t_, err := conn.Do(\"LPUSH\", rl.id, value)\n\treturn err\n}\n\n// Default Add, aliased to List.AddStart\nfunc (rl *List) Add(value string) error {\n\treturn rl.AddStart(value)\n}\n\n// Get all elements of a list\nfunc (rl *List) All() ([]string, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tresult, err := redis.Values(conn.Do(\"LRANGE\", rl.id, \"0\", \"-1\"))\n\tstrs := make([]string, len(result))\n\tfor i := 0; i < len(result); i++ {\n\t\tstrs[i] = getString(result, i)\n\t}\n\treturn strs, err\n}\n\n// Deprecated\nfunc (rl *List) GetAll() ([]string, error) {\n\treturn rl.All()\n}\n\n// Get the last element of a list\nfunc (rl *List) Last() (string, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tresult, err := redis.Values(conn.Do(\"LRANGE\", rl.id, \"-1\", \"-1\"))\n\tif len(result) == 1 {\n\t\treturn getString(result, 0), err\n\t}\n\treturn \"\", err\n}\n\n// Deprecated\nfunc (rl *List) GetLast() (string, error) {\n\treturn rl.Last()\n}\n\n// Get the last N elements of a list\nfunc (rl *List) LastN(n int) ([]string, error) {\n\tconn := rl.pool.Get(rl.dbindex)\n\tresult, err := redis.Values(conn.Do(\"LRANGE\", rl.id, \"-\"+strconv.Itoa(n), \"-1\"))\n\tstrs := make([]string, len(result))\n\tfor i := 0; i < len(result); i++ {\n\t\tstrs[i] = getString(result, i)\n\t}\n\treturn strs, err\n}\n\n// Deprecated\nfunc (rl *List) GetLastN(n int) ([]string, error) {\n\treturn rl.LastN(n)\n}\n\n// Remove the first occurrence of an element from the list\nfunc (rl *List) RemoveElement(value string) error {\n\tconn := rl.pool.Get(rl.dbindex)\n\t_, err := conn.Do(\"LREM\", rl.id, value)\n\treturn err\n}\n\n// Set element of list at index n to value\nfunc (rl *List) Set(index int64, value string) error {\n\tconn := rl.pool.Get(rl.dbindex)\n\t_, err := conn.Do(\"LSET\", rl.id, index, value)\n\treturn err\n}\n\n// Trim an existing list so that it will contain only the specified range of\n// elements specified.\nfunc (rl *List) Trim(start, stop int64) error {\n\tconn := rl.pool.Get(rl.dbindex)\n\t_, err := conn.Do(\"LTRIM\", rl.id, start, stop)\n\treturn err\n}\n\n// Remove this list\nfunc (rl *List) Remove() error {\n\tconn := rl.pool.Get(rl.dbindex)\n\t_, err := conn.Do(\"DEL\", rl.id)\n\treturn err\n}\n\n// Clear the contents\nfunc (rl *List) Clear() error {\n\treturn rl.Remove()\n}\n\n/* --- Set functions --- */\n\n// Create a new set\nfunc NewSet(pool *ConnectionPool, id string) *Set {\n\treturn &Set{pool, id, 0}\n}\n\n// Select a different database\nfunc (rs *Set) SelectDatabase(dbindex int) {\n\trs.dbindex = dbindex\n}\n\n// Add an element to the set\nfunc (rs *Set) Add(value string) error {\n\tconn := rs.pool.Get(rs.dbindex)\n\t_, err := conn.Do(\"SADD\", rs.id, value)\n\treturn err\n}\n\n// Returns the set cardinality (number of elements) of the set\nfunc (rs *Set) Size() (int64, error) {\n\tconn := rs.pool.Get(rs.dbindex)\n\tsize, err := conn.Do(\"SCARD\", rs.id)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.Int64(size, err)\n}\n\n// Check if a given value is in the set\nfunc (rs *Set) Has(value string) (bool, error) {\n\tconn := rs.pool.Get(rs.dbindex)\n\tretval, err := conn.Do(\"SISMEMBER\", rs.id, value)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.Bool(retval, err)\n}\n\n// Get all elements of the set\nfunc (rs *Set) All() ([]string, error) {\n\tconn := rs.pool.Get(rs.dbindex)\n\tresult, err := redis.Values(conn.Do(\"SMEMBERS\", rs.id))\n\tstrs := make([]string, len(result))\n\tfor i := 0; i < len(result); i++ {\n\t\tstrs[i] = getString(result, i)\n\t}\n\treturn strs, err\n}\n\n// Deprecated\nfunc (rs *Set) GetAll() ([]string, error) {\n\treturn rs.All()\n}\n\n// Remove a random member from the set\nfunc (rs *Set) Pop() (string, error) {\n\tconn := rs.pool.Get(rs.dbindex)\n\tresult, err := conn.Do(\"SPOP\", rs.id)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.String(result, err)\n}\n\n// Get a random member of the set\nfunc (rs *Set) Random() (string, error) {\n\tconn := rs.pool.Get(rs.dbindex)\n\tresult, err := conn.Do(\"SRANDMEMBER\", rs.id)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.String(result, err)\n}\n\n// Remove an element from the set\nfunc (rs *Set) Del(value string) error {\n\tconn := rs.pool.Get(rs.dbindex)\n\t_, err := conn.Do(\"SREM\", rs.id, value)\n\treturn err\n}\n\n// Remove this set\nfunc (rs *Set) Remove() error {\n\tconn := rs.pool.Get(rs.dbindex)\n\t_, err := conn.Do(\"DEL\", rs.id)\n\treturn err\n}\n\n// Clear the contents\nfunc (rs *Set) Clear() error {\n\treturn rs.Remove()\n}\n\n/* --- HashMap functions --- */\n\n// Create a new hashmap\nfunc NewHashMap(pool *ConnectionPool, id string) *HashMap {\n\treturn &HashMap{pool, id, 0}\n}\n\n// Select a different database\nfunc (rh *HashMap) SelectDatabase(dbindex int) {\n\trh.dbindex = dbindex\n}\n\n// Set a value in a hashmap given the element id (for instance a user id) and the key (for instance \"password\")\nfunc (rh *HashMap) Set(elementid, key, value string) error {\n\tconn := rh.pool.Get(rh.dbindex)\n\t_, err := conn.Do(\"HSET\", rh.id+\":\"+elementid, key, value)\n\treturn err\n}\n\n// Given an element id, set a key and a value together with an expiration time\nfunc (rh *HashMap) SetExpire(elementid, key, value string, expire time.Duration) error {\n\tconn := rh.pool.Get(rh.dbindex)\n\tif _, err := conn.Do(\"HSET\", rh.id+\":\"+elementid, key, value); err != nil {\n\t\treturn err\n\t}\n\t// No EXPIRE in Redis for hash keys, as far as I can tell from the documentation.\n\t// This is the manual way.\n\tgo func() {\n\t\ttime.Sleep(expire)\n\t\trh.DelKey(elementid, key)\n\t}()\n\t// Set the elementid to expire in the given duration (as milliseconds)\n\t//expireMilliseconds := expire.Nanoseconds() / 1000000\n\t//if _, err := conn.Do(\"PEXPIRE\", rh.id+\":\"+elementid, expireMilliseconds); err != nil {\n\t//\treturn err\n\t//}\n\treturn nil\n}\n\n// Commented out because this would only return TTL for the elementid, not for the key\n// TimeToLive returns how long a key has to live until it expires\n// Returns a duration of 0 when the time has passed\n//func (rh *HashMap) TimeToLive(elementid string) (time.Duration, error) {\n//\tconn := rh.pool.Get(rh.dbindex)\n//\tttlSecondsInterface, err := conn.Do(\"TTL\", rh.id+\":\"+elementid)\n//\tif err != nil || ttlSecondsInterface.(int64) <= 0 {\n//\t\treturn time.Duration(0), err\n//\t}\n//\tns := time.Duration(ttlSecondsInterface.(int64)) * time.Second\n//\treturn ns, nil\n//}\n\n// Get a value from a hashmap given the element id (for instance a user id) and the key (for instance \"password\")\nfunc (rh *HashMap) Get(elementid, key string) (string, error) {\n\tconn := rh.pool.Get(rh.dbindex)\n\tresult, err := redis.String(conn.Do(\"HGET\", rh.id+\":\"+elementid, key))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn result, nil\n}\n\n// Check if a given elementid + key is in the hash map\nfunc (rh *HashMap) Has(elementid, key string) (bool, error) {\n\tconn := rh.pool.Get(rh.dbindex)\n\tretval, err := conn.Do(\"HEXISTS\", rh.id+\":\"+elementid, key)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn redis.Bool(retval, err)\n}\n\n// Keys returns the keys of the given elementid.\nfunc (rh *HashMap) Keys(elementid string) ([]string, error) {\n\tconn := rh.pool.Get(rh.dbindex)\n\tresult, err := redis.Values(conn.Do(\"HKEYS\", rh.id+\":\"+elementid))\n\tstrs := make([]string, len(result))\n\tfor i := 0; i < len(result); i++ {\n\t\tstrs[i] = getString(result, i)\n\t}\n\treturn strs, err\n}\n\n// Check if a given elementid exists as a hash map at all\nfunc (rh *HashMap) Exists(elementid string) (bool, error) {\n\t// TODO: key is not meant to be a wildcard, check for \"*\"\n\treturn hasKey(rh.pool, rh.id+\":\"+elementid, rh.dbindex)\n}\n\n// Get all elementid's for all hash elements\nfunc (rh *HashMap) All() ([]string, error) {\n\tconn := rh.pool.Get(rh.dbindex)\n\tresult, err := redis.Values(conn.Do(\"KEYS\", rh.id+\":*\"))\n\tstrs := make([]string, len(result))\n\tidlen := len(rh.id)\n\tfor i := 0; i < len(result); i++ {\n\t\tstrs[i] = getString(result, i)[idlen+1:]\n\t}\n\treturn strs, err\n}\n\n// Deprecated\nfunc (rh *HashMap) GetAll() ([]string, error) {\n\treturn rh.All()\n}\n\n// Remove a key for an entry in a hashmap (for instance the email field for a user)\nfunc (rh *HashMap) DelKey(elementid, key string) error {\n\tconn := rh.pool.Get(rh.dbindex)\n\t_, err := conn.Do(\"HDEL\", rh.id+\":\"+elementid, key)\n\treturn err\n}\n\n// Remove an element (for instance a user)\nfunc (rh *HashMap) Del(elementid string) error {\n\tconn := rh.pool.Get(rh.dbindex)\n\t_, err := conn.Do(\"DEL\", rh.id+\":\"+elementid)\n\treturn err\n}\n\n// Remove this hashmap (all keys that starts with this hashmap id and a colon)\nfunc (rh *HashMap) Remove() error {\n\tconn := rh.pool.Get(rh.dbindex)\n\t// Find all hashmap keys that starts with rh.id+\":\"\n\tresults, err := redis.Values(conn.Do(\"KEYS\", rh.id+\":*\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\t// For each key id\n\tfor i := 0; i < len(results); i++ {\n\t\t// Delete this key\n\t\tif _, err = conn.Do(\"DEL\", getString(results, i)); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// Clear the contents\nfunc (rh *HashMap) Clear() error {\n\treturn rh.Remove()\n}\n\n/* --- KeyValue functions --- */\n\n// Create a new key/value\nfunc NewKeyValue(pool *ConnectionPool, id string) *KeyValue {\n\treturn &KeyValue{pool, id, 0}\n}\n\n// Select a different database\nfunc (rkv *KeyValue) SelectDatabase(dbindex int) {\n\trkv.dbindex = dbindex\n}\n\n// Set a key and value\nfunc (rkv *KeyValue) Set(key, value string) error {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\t_, err := conn.Do(\"SET\", rkv.id+\":\"+key, value)\n\treturn err\n}\n\n// Set a key and value, with expiry\nfunc (rkv *KeyValue) SetExpire(key, value string, expire time.Duration) error {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\t// Convert from nanoseconds to milliseconds\n\texpireMilliseconds := expire.Nanoseconds() / 1000000\n\t// Set the value, together with an expiry time, given in milliseconds\n\t_, err := conn.Do(\"SET\", rkv.id+\":\"+key, value, \"PX\", expireMilliseconds)\n\treturn err\n}\n\n// TimeToLive returns how long a key has to live until it expires\n// Returns a duration of 0 when the time has passed\nfunc (rkv *KeyValue) TimeToLive(key string) (time.Duration, error) {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\tttlSecondsInterface, err := conn.Do(\"TTL\", rkv.id+\":\"+key)\n\tif err != nil || ttlSecondsInterface.(int64) <= 0 {\n\t\treturn time.Duration(0), err\n\t}\n\tns := time.Duration(ttlSecondsInterface.(int64)) * time.Second\n\treturn ns, nil\n}\n\n// Get a value given a key\nfunc (rkv *KeyValue) Get(key string) (string, error) {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\tresult, err := redis.String(conn.Do(\"GET\", rkv.id+\":\"+key))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn result, nil\n}\n\n// Remove a key\nfunc (rkv *KeyValue) Del(key string) error {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\t_, err := conn.Do(\"DEL\", rkv.id+\":\"+key)\n\treturn err\n}\n\n// Increase the value of a key, returns the new value\n// Returns an empty string if there were errors,\n// or \"0\" if the key does not already exist.\nfunc (rkv *KeyValue) Inc(key string) (string, error) {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\tresult, err := redis.Int64(conn.Do(\"INCR\", rkv.id+\":\"+key))\n\tif err != nil {\n\t\treturn \"0\", err\n\t}\n\treturn strconv.FormatInt(result, 10), nil\n}\n\n// Remove this key/value\nfunc (rkv *KeyValue) Remove() error {\n\tconn := rkv.pool.Get(rkv.dbindex)\n\t// Find all keys that starts with rkv.id+\":\"\n\tresults, err := redis.Values(conn.Do(\"KEYS\", rkv.id+\":*\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\t// For each key id\n\tfor i := 0; i < len(results); i++ {\n\t\t// Delete this key\n\t\tif _, err = conn.Do(\"DEL\", getString(results, i)); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// Clear the contents\nfunc (rkv *KeyValue) Clear() error {\n\treturn rkv.Remove()\n}\n\n// --- Generic redis functions ---\n\n// Check if a key exists. The key can be a wildcard (ie. \"user*\").\nfunc hasKey(pool *ConnectionPool, wildcard string, dbindex int) (bool, error) {\n\tconn := pool.Get(dbindex)\n\tresult, err := redis.Values(conn.Do(\"KEYS\", wildcard))\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn len(result) > 0, nil\n}\n\n// --- Related to setting and retrieving timeout values\n\n// SetConnectTimeout sets the connect timeout for new connections\nfunc SetConnectTimeout(t time.Duration) {\n\tconnectTimeout = t\n}\n\n// SetReadTimeout sets the read timeout for new connections\nfunc SetReadTimeout(t time.Duration) {\n\treadTimeout = t\n}\n\n// SetWriteTimeout sets the write timeout for new connections\nfunc SetWriteTimeout(t time.Duration) {\n\twriteTimeout = t\n}\n\n// SetIdleTimeout sets the idle timeout for new connections\nfunc SetIdleTimeout(t time.Duration) {\n\tidleTimeout = t\n}\n\n// ConnectTimeout returns the current connect timeout for new connections\nfunc ConnectTimeout() time.Duration {\n\treturn connectTimeout\n}\n\n// ReadTimeout returns the current read timeout for new connections\nfunc ReadTimeout() time.Duration {\n\treturn readTimeout\n}\n\n// WriteTimeout returns the current write timeout for new connections\nfunc WriteTimeout() time.Duration {\n\treturn writeTimeout\n}\n\n// IdleTimeout returns the current idle timeout for new connections\nfunc IdleTimeout() time.Duration {\n\treturn idleTimeout\n}\n"
  },
  {
    "path": "examples/web/vendor/modules.txt",
    "content": "# github.com/codegangsta/negroni v1.0.0\n## explicit\ngithub.com/codegangsta/negroni\n# github.com/gomodule/redigo v1.8.9\n## explicit; go 1.16\ngithub.com/gomodule/redigo/redis\n# github.com/gorilla/mux v1.8.1\n## explicit; go 1.20\ngithub.com/gorilla/mux\n# github.com/xyproto/pinterface v1.5.3\n## explicit; go 1.8\ngithub.com/xyproto/pinterface\n# github.com/xyproto/simpleredis/v2 v2.6.5\n## explicit; go 1.17\ngithub.com/xyproto/simpleredis/v2\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/kubernetes/kompose\n\ngo 1.24.0\n\nreplace github.com/openshift/api v3.9.0+incompatible => github.com/openshift/api v0.0.0-20230704153349-abb98ff04d03\n\nrequire (\n\tgithub.com/compose-spec/compose-go/v2 v2.10.0\n\tgithub.com/deckarep/golang-set v1.8.0\n\tgithub.com/fatih/structs v1.1.0\n\tgithub.com/fsouza/go-dockerclient v1.12.3\n\tgithub.com/google/go-cmp v0.7.0\n\tgithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510\n\tgithub.com/joho/godotenv v1.5.1\n\tgithub.com/mattn/go-shellwords v1.0.12\n\tgithub.com/novln/docker-parser v1.0.0\n\tgithub.com/openshift/api v3.9.0+incompatible\n\tgithub.com/pkg/errors v0.9.1\n\tgithub.com/sirupsen/logrus v1.9.4\n\tgithub.com/spf13/cast v1.10.0\n\tgithub.com/spf13/cobra v1.10.2\n\tgithub.com/spf13/pflag v1.0.10\n\tgithub.com/spf13/viper v1.18.2\n\tgolang.org/x/tools/godoc v0.1.0-deprecated\n\tgopkg.in/yaml.v3 v3.0.1\n\tgotest.tools/v3 v3.5.2\n\tk8s.io/api v0.31.2\n\tk8s.io/apimachinery v0.31.2\n)\n\nrequire (\n\tgithub.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect\n\tgithub.com/Microsoft/go-winio v0.6.2 // indirect\n\tgithub.com/containerd/log v0.1.0 // indirect\n\tgithub.com/distribution/reference v0.6.0 // indirect\n\tgithub.com/docker/docker v28.5.2+incompatible // indirect\n\tgithub.com/docker/go-connections v0.5.0 // indirect\n\tgithub.com/docker/go-units v0.5.0 // indirect\n\tgithub.com/fsnotify/fsnotify v1.7.0 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.7.0 // indirect\n\tgithub.com/go-logr/logr v1.4.2 // indirect\n\tgithub.com/go-viper/mapstructure/v2 v2.4.0 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/hashicorp/hcl v1.0.0 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/klauspost/compress v1.18.0 // indirect\n\tgithub.com/magiconair/properties v1.8.7 // indirect\n\tgithub.com/mitchellh/mapstructure v1.5.0 // indirect\n\tgithub.com/moby/docker-image-spec v1.3.1 // indirect\n\tgithub.com/moby/go-archive v0.1.0 // indirect\n\tgithub.com/moby/patternmatcher v0.6.0 // indirect\n\tgithub.com/moby/sys/sequential v0.6.0 // indirect\n\tgithub.com/moby/sys/user v0.4.0 // indirect\n\tgithub.com/moby/sys/userns v0.1.0 // indirect\n\tgithub.com/moby/term v0.5.0 // 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/morikuni/aec v1.0.0 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/opencontainers/image-spec v1.1.0 // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.2.1 // indirect\n\tgithub.com/sagikazarmark/locafero v0.4.0 // indirect\n\tgithub.com/sagikazarmark/slog-shim v0.1.0 // indirect\n\tgithub.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect\n\tgithub.com/sourcegraph/conc v0.3.0 // indirect\n\tgithub.com/spf13/afero v1.11.0 // indirect\n\tgithub.com/subosito/gotenv v1.6.0 // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgithub.com/xhit/go-str2duration/v2 v2.1.0 // indirect\n\tgo.uber.org/multierr v1.11.0 // indirect\n\tgo.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect\n\tgolang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect\n\tgolang.org/x/net v0.49.0 // indirect\n\tgolang.org/x/sync v0.19.0 // indirect\n\tgolang.org/x/sys v0.40.0 // indirect\n\tgolang.org/x/text v0.33.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/ini.v1 v1.67.0 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // 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)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=\ngithub.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=\ngithub.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=\ngithub.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=\ngithub.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=\ngithub.com/compose-spec/compose-go/v2 v2.10.0 h1:K2C5LQ3KXvkYpy5N/SG6kIYB90iiAirA9btoTh/gB0Y=\ngithub.com/compose-spec/compose-go/v2 v2.10.0/go.mod h1:Ohac1SzhO/4fXXrzWIztIVB6ckmKBv1Nt5Z5mGVESUg=\ngithub.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=\ngithub.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=\ngithub.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=\ngithub.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=\ngithub.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=\ngithub.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=\ngithub.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=\ngithub.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=\ngithub.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=\ngithub.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=\ngithub.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=\ngithub.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=\ngithub.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=\ngithub.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=\ngithub.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=\ngithub.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=\ngithub.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=\ngithub.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=\ngithub.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=\ngithub.com/fsouza/go-dockerclient v1.12.3 h1:CEsX4/msyMEekHAR9Pf8XniZBtwGo0Kl+mLPQ/AnSys=\ngithub.com/fsouza/go-dockerclient v1.12.3/go.mod h1:gl0t2KUfrsLbm4tw5/ySsJkkFpi7Fz9gXzY2BKLEvZA=\ngithub.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=\ngithub.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=\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-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=\ngithub.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\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/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=\ngithub.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=\ngithub.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=\ngithub.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=\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/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/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=\ngithub.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=\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/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=\ngithub.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=\ngithub.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=\ngithub.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=\ngithub.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=\ngithub.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=\ngithub.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=\ngithub.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=\ngithub.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=\ngithub.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=\ngithub.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=\ngithub.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=\ngithub.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=\ngithub.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=\ngithub.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=\ngithub.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=\ngithub.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=\ngithub.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=\ngithub.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=\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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=\ngithub.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=\ngithub.com/novln/docker-parser v1.0.0 h1:PjEBd9QnKixcWczNGyEdfUrP6GR0YUilAqG7Wksg3uc=\ngithub.com/novln/docker-parser v1.0.0/go.mod h1:oCeM32fsoUwkwByB5wVjsrsVQySzPWkl3JdlTn1txpE=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=\ngithub.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=\ngithub.com/openshift/api v0.0.0-20230704153349-abb98ff04d03 h1:qMeI0T0VAk3ydumBleYCbR7P2clyyEophp+dBCtCrJA=\ngithub.com/openshift/api v0.0.0-20230704153349-abb98ff04d03/go.mod h1:yimSGmjsI+XF1mr+AKBs2//fSXIOhhetHGbMlBEfXbs=\ngithub.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg=\ngithub.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=\ngithub.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=\ngithub.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=\ngithub.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=\ngithub.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=\ngithub.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=\ngithub.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=\ngithub.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=\ngithub.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=\ngithub.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=\ngithub.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=\ngithub.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=\ngithub.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=\ngithub.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=\ngithub.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=\ngithub.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=\ngithub.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=\ngithub.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=\ngithub.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=\ngithub.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=\ngithub.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=\ngithub.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=\ngithub.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=\ngithub.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngo.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=\ngo.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=\ngo.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=\ngo.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=\ngo.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=\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/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=\ngolang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=\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.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=\ngolang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=\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/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=\ngolang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=\ngolang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=\ngolang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=\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.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=\ngolang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=\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/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=\ngolang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=\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=\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/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=\ngopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=\ngotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=\nk8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=\nk8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=\nk8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=\nk8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=\nk8s.io/utils v0.0.0-20240711033017-18e509b52bc8/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": "gover.coverprofile",
    "content": "mode: atomic\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:44.68,82.102 3 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:87.2,87.43 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:91.2,91.68 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:142.2,142.18 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:82.102,84.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:87.43,89.3 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:91.68,96.32 3 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:96.32,98.69 1 174\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:98.69,99.38 1 69\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:99.38,102.75 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:109.6,110.32 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:118.6,118.108 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:136.6,137.37 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:102.75,103.27 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:103.27,105.16 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:110.32,112.108 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:112.108,114.16 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:118.108,121.45 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:131.7,131.36 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:121.45,122.76 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:122.76,125.82 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:125.82,127.15 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:131.36,132.16 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:146.75,150.29 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:163.2,166.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:150.29,152.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:157.3,157.67 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:160.3,160.27 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:152.17,154.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:157.67,159.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:169.48,171.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:174.3,174.28 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:176.74,178.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:181.3,181.28 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:182.10,183.133 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:171.17,173.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:178.17,180.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:187.54,194.16 4 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:198.2,199.16 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:203.2,203.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:194.16,196.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/compose.go:199.16,201.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:81.52,83.27 2 8\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:120.2,120.13 1 8\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:83.27,87.10 4 8\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:102.3,102.22 1 8\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:88.41,89.18 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:90.41,91.19 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:92.41,93.19 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:94.41,95.27 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:95.27,97.5 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:97.10,99.5 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:102.22,107.4 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:107.9,110.23 2 6\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:113.4,116.6 1 6\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:110.23,112.5 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:125.61,127.40 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:134.2,134.37 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:127.40,129.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:132.3,132.48 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:129.17,131.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:137.60,138.38 1 7\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:139.23,140.47 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:141.18,142.46 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:143.22,144.50 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:145.18,146.34 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:147.10,148.132 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:152.53,154.2 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:156.51,159.2 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:161.46,163.2 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:165.60,169.16 4 4\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:172.2,173.20 2 4\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:169.16,171.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:177.48,178.21 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:186.2,186.34 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:178.21,179.23 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:184.3,184.24 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/utils.go:179.23,183.4 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:43.63,48.35 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:52.2,52.38 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:68.2,70.16 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:74.2,75.36 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:80.2,81.16 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:85.2,85.27 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:48.35,50.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:52.38,54.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:57.3,64.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:54.17,56.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:70.16,72.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:75.36,77.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:81.16,83.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:90.81,94.34 3 9\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:142.2,142.23 1 9\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:147.2,147.19 1 9\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:166.2,166.16 1 9\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:94.34,97.55 2 11\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:104.3,105.17 2 11\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:112.3,112.26 1 11\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:119.3,120.21 2 11\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:123.3,125.27 2 11\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:97.55,98.72 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:101.4,101.21 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:98.72,100.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:105.17,107.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:112.26,113.25 1 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:113.25,116.5 2 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:120.21,122.4 1 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:125.27,127.18 2 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:130.4,130.27 1 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:127.18,129.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:130.27,137.5 1 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:142.23,145.3 1 26\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:147.19,148.31 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:148.31,151.40 3 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:157.4,157.34 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:151.40,155.5 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:157.34,162.5 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:170.96,179.77 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:286.2,288.27 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:179.77,186.52 7 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:189.3,201.47 10 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:206.3,207.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:210.3,214.42 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:224.3,224.89 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:228.3,229.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:234.3,251.48 15 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:256.3,256.43 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:273.3,274.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:277.3,280.42 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:186.52,188.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:201.47,203.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:207.17,209.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:214.42,215.64 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:215.64,218.5 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:224.89,226.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:229.17,231.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:251.48,254.4 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:256.43,257.55 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:257.55,258.66 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:258.66,259.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:259.33,261.21 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:264.7,264.49 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:267.7,267.82 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:261.21,263.8 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:264.49,266.8 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:274.17,276.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:280.42,282.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:292.57,293.49 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:293.49,296.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:300.3,302.44 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:296.17,298.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:306.74,307.73 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:310.2,310.12 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:307.73,309.3 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:314.112,316.62 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:363.2,363.8 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:316.62,318.76 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:318.76,321.18 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:324.4,326.18 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:330.4,330.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:347.4,347.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:321.18,323.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:326.18,328.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:330.29,333.11 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:344.5,344.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:333.11,335.24 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:342.6,342.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:335.24,338.7 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:338.12,341.7 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:347.29,349.38 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:349.38,353.6 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:356.8,359.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:359.17,361.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:367.75,368.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:373.2,373.13 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:368.29,369.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:369.32,371.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:377.78,381.30 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:394.2,394.21 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:381.30,384.17 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:387.3,391.31 5 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:384.17,386.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:398.85,399.26 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:404.2,404.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:399.26,400.39 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:400.39,402.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:408.51,410.26 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:417.2,417.22 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:410.26,412.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:415.3,415.40 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v1v2.go:412.17,414.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:44.52,47.24 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:55.2,55.20 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:47.24,49.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:52.3,53.24 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:49.32,51.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:61.61,67.16 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:72.2,73.16 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:77.2,78.29 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:122.2,123.36 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:128.2,129.16 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:133.2,133.27 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:67.16,69.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:73.16,75.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:78.29,81.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:86.3,87.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:92.3,109.17 4 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:112.3,112.20 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:81.17,83.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:87.17,89.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:109.17,111.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:112.20,114.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:114.9,116.18 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:116.18,118.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:123.36,125.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:129.16,131.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:136.67,145.42 3 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:170.2,170.42 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:179.2,179.25 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:145.42,147.36 2 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:150.3,151.17 2 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:156.3,157.17 2 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:162.3,162.24 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:147.36,149.4 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:151.17,153.12 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:157.17,159.12 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:162.24,164.4 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:164.9,164.34 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:164.34,166.4 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:170.42,173.17 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:177.3,177.77 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:173.17,175.12 2 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:183.61,184.21 1 5\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:194.2,195.31 2 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:185.23,186.39 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:187.39,188.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:189.10,190.53 1 5\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:190.53,192.4 1 4\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:202.66,204.30 2 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:218.2,218.17 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:204.30,208.23 2 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:212.3,212.19 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:216.3,216.33 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:208.23,210.4 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:212.19,214.4 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:223.84,228.29 3 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:242.2,242.19 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:264.2,264.21 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:228.29,240.3 2 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:242.19,243.31 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:243.31,246.40 3 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:252.4,252.33 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:255.4,260.6 1 2\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:246.40,250.5 3 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:252.33,253.13 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:270.82,276.33 5 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:313.2,313.19 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:324.2,334.8 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:276.33,277.14 1 16\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:278.36,279.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:280.33,281.22 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:284.40,285.20 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:286.40,287.34 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:288.36,289.33 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:290.37,292.18 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:295.4,295.37 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:296.36,298.18 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:301.4,301.36 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:302.36,303.33 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:304.40,306.18 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:309.4,309.40 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:281.22,283.5 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:292.18,294.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:298.18,300.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:306.18,308.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:313.19,314.24 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:319.3,319.49 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:314.24,317.4 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:319.49,321.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:340.117,346.39 4 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:354.2,354.40 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:362.2,362.39 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:366.2,366.43 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:374.2,374.36 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:378.2,378.33 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:390.2,399.8 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:346.39,348.17 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:351.3,351.35 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:348.17,350.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:354.40,356.17 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:359.3,359.36 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:356.17,358.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:362.39,364.3 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:366.43,368.17 2 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:371.3,371.39 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:368.17,370.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:374.36,376.3 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:378.33,379.14 1 3\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:380.39,381.20 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:382.39,383.34 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:384.35,385.33 1 1\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:402.96,413.62 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:539.2,541.27 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:413.62,438.50 22 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:442.3,444.81 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:450.3,455.91 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:464.3,465.25 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:474.3,475.55 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:478.3,478.48 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:484.3,484.50 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:489.3,491.54 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:498.3,521.89 9 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:526.3,526.42 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:530.3,532.56 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:536.3,536.76 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:438.50,440.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:444.81,446.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:455.91,458.18 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:458.18,460.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:465.25,467.27 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:467.27,469.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:475.55,477.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:478.48,481.4 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:484.50,486.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:491.54,493.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:521.89,523.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:526.42,528.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:532.56,534.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:546.61,547.19 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:551.2,552.20 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:556.2,556.16 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:547.19,549.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:552.20,554.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:559.131,560.45 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:560.45,561.66 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:561.66,563.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:564.8,566.50 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:566.50,571.21 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:574.4,574.66 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:571.21,573.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:579.110,580.66 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:612.2,612.12 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:580.66,589.58 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:600.3,600.64 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:589.58,592.67 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:592.67,594.19 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:597.5,597.52 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:594.19,596.6 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:600.64,603.73 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:603.73,605.19 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:608.5,608.64 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:605.19,607.6 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:615.106,620.60 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:620.60,622.19 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:632.3,632.69 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:622.19,624.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:624.9,626.10 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:626.10,628.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:628.10,629.13 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:637.95,642.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:646.2,646.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:670.2,670.79 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:674.2,674.101 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:678.2,678.68 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:682.2,682.12 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:642.33,644.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:646.33,647.14 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:648.25,650.18 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:654.4,654.43 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:655.27,656.76 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:657.26,658.52 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:659.36,660.42 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:661.29,662.41 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:663.29,664.41 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:665.11,666.37 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:650.18,652.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:670.79,672.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:674.101,676.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:678.68,680.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:685.99,686.49 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:686.49,689.17 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:692.3,692.34 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:703.3,705.44 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:689.17,691.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:692.34,694.42 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:694.42,700.5 4 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:709.94,712.40 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:722.2,722.23 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:712.40,713.41 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:713.41,714.36 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:714.36,716.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:716.10,716.47 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:716.47,718.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:725.100,726.44 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:729.2,730.50 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:734.2,734.46 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:941.2,941.48 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:946.2,946.46 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:951.2,951.46 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:956.2,956.46 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:960.2,960.24 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:726.44,728.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:730.50,732.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:734.46,736.66 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:742.3,743.37 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:746.3,746.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:749.3,749.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:752.3,752.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:755.3,755.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:758.3,758.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:761.3,761.34 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:764.3,764.81 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:767.3,767.34 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:770.3,770.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:773.3,773.45 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:777.3,777.51 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:780.3,780.37 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:784.3,784.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:791.3,791.28 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:795.3,795.34 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:799.3,799.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:802.3,802.35 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:805.3,805.36 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:811.3,811.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:814.3,814.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:818.3,818.38 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:822.3,822.35 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:825.3,825.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:828.3,828.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:831.3,831.26 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:835.3,835.24 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:838.3,838.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:847.3,847.30 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:850.3,850.29 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:853.3,853.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:856.3,856.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:859.3,859.33 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:862.3,862.24 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:865.3,865.30 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:869.3,869.53 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:872.3,872.49 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:875.3,875.28 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:878.3,878.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:881.3,881.36 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:884.3,884.51 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:887.3,887.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:890.3,890.30 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:894.3,894.39 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:897.3,897.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:900.3,900.25 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:903.3,903.32 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:934.3,934.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:937.3,937.45 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:736.66,738.12 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:739.9,741.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:743.37,745.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:746.31,748.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:749.32,751.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:752.33,754.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:755.32,757.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:758.32,760.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:761.34,763.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:764.81,766.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:767.34,769.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:770.32,772.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:773.45,775.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:777.51,779.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:780.37,782.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:784.32,789.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:791.28,794.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:795.34,798.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:799.31,801.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:802.35,804.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:805.36,807.42 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:807.42,809.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:811.32,813.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:814.31,817.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:818.38,821.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:822.35,824.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:825.29,827.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:828.33,830.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:831.26,833.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:835.24,837.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:838.31,840.35 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:843.4,843.37 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:840.35,842.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:843.37,845.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:847.30,849.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:850.29,852.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:853.31,855.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:856.32,858.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:859.33,861.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:862.24,864.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:865.30,868.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:869.53,871.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:872.49,874.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:875.28,877.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:878.32,880.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:881.36,883.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:884.51,886.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:887.31,889.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:890.30,893.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:894.39,896.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:897.32,899.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:900.25,902.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:903.32,913.52 3 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:918.4,918.46 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:926.4,928.29 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:932.4,932.35 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:913.52,916.5 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:918.46,919.57 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:922.5,922.51 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:919.57,921.6 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:928.29,930.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:934.31,936.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:941.48,943.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:946.46,948.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:951.46,953.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:956.46,958.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:963.69,964.26 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:968.2,970.49 2 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:985.2,985.47 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:991.2,991.18 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:964.26,966.3 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:970.49,971.45 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:980.3,980.81 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:971.45,972.27 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:975.4,975.27 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:972.27,974.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:975.27,977.5 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:980.81,982.4 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:985.47,986.31 1 0\ngithub.com/kubernetes/kompose/pkg/loader/compose/v3.go:986.31,988.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:42.28,45.2 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:48.50,49.19 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:53.2,53.44 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:58.2,59.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:62.2,62.15 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:49.19,51.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:53.44,54.55 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:54.55,56.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:59.16,61.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:66.81,67.32 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:70.2,70.28 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:67.32,69.3 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:73.81,78.29 3 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:83.2,83.31 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:89.2,89.29 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:95.2,100.60 2 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:110.2,112.29 3 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:115.2,115.86 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:119.2,119.8 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:78.29,80.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:83.31,86.3 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:89.29,92.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:100.60,104.3 3 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:104.8,104.69 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:104.69,107.3 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:112.29,114.3 1 5\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:115.86,118.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:131.88,138.41 2 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:162.2,162.22 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:180.2,180.32 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:186.2,186.27 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:195.2,195.8 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:138.41,139.10 1 52\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:140.37,141.24 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:146.4,147.29 2 17\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:151.4,152.35 2 17\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:154.25,155.47 1 5\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:156.11,157.37 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:141.24,144.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:147.29,150.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:162.22,163.36 1 7\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:163.36,165.4 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:165.9,165.62 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:165.62,167.4 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:168.8,168.29 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:168.29,171.3 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:171.8,171.28 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:171.28,174.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:180.32,183.3 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:186.27,188.3 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:188.8,188.34 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:188.34,191.3 2 9\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:191.8,194.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:200.48,202.2 1 78\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:206.52,207.32 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:211.2,211.16 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:207.32,210.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:214.36,216.2 1 66\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:219.50,221.2 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:224.75,228.24 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:231.2,231.15 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:228.24,230.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:236.85,238.33 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:243.2,243.13 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:238.33,239.42 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:239.42,241.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:247.73,249.46 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:253.2,253.36 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:257.2,260.16 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:263.2,266.42 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:270.2,270.20 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:249.46,251.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:253.36,255.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:260.16,262.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:266.42,268.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:274.135,276.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:281.2,281.14 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:298.2,298.18 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:276.18,278.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:278.8,280.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:281.14,284.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:284.8,284.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:284.21,286.77 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:289.3,289.11 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:286.77,288.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:290.8,293.60 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:296.3,296.71 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:293.60,295.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:302.49,303.46 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:308.2,308.17 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:303.46,305.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:305.8,305.54 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:305.54,307.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:315.30,317.2 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:321.40,323.2 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:326.35,328.2 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:331.61,334.40 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:341.2,342.37 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:334.40,336.17 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:339.3,339.48 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:336.17,338.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:346.73,348.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:352.2,357.32 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:360.2,362.46 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:366.2,367.25 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:371.2,372.51 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:383.2,384.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:390.2,393.16 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:397.2,397.12 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:348.16,350.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:357.32,359.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:362.46,364.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:367.25,369.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:372.51,374.22 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:379.3,379.81 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:374.22,376.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:376.9,378.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:384.16,386.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:393.16,395.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:401.114,402.20 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:410.2,414.25 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:419.2,420.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:424.2,425.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:429.2,429.33 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:439.2,441.16 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:445.2,445.12 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:402.20,404.34 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:407.3,407.13 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:404.34,406.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:414.25,417.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:420.16,422.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:425.16,427.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:429.33,434.17 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:434.17,436.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/utils.go:441.16,443.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:53.41,63.16 5 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:67.2,67.16 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:80.2,82.16 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:87.2,98.16 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:101.2,105.16 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:109.2,110.12 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:63.16,65.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:67.16,69.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:73.3,74.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:69.17,71.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:74.17,76.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:82.16,84.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:98.16,100.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:105.16,107.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:114.39,117.16 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:120.2,124.16 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:129.2,129.22 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:132.2,132.19 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:117.16,119.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:124.16,126.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:129.22,131.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:135.52,137.19 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:147.2,147.16 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:137.19,139.22 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:139.22,143.4 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:143.9,145.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:150.62,159.2 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:162.76,168.77 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:175.2,176.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:179.2,179.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:182.2,182.15 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:193.2,197.30 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:276.2,276.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:282.2,282.12 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:168.77,169.63 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:169.63,171.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:176.16,178.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:179.21,181.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:182.15,184.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:187.3,187.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:190.3,190.18 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:184.17,186.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:187.28,189.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:197.30,200.34 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:209.3,212.17 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:215.3,216.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:219.3,220.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:223.3,223.34 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:200.34,202.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:206.4,206.65 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:202.18,204.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:212.17,214.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:216.17,218.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:220.17,222.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:224.8,226.22 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:230.3,230.57 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:234.3,236.29 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:226.22,228.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:230.57,232.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:236.29,238.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:241.4,242.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:246.4,249.52 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:268.4,269.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:273.4,273.31 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:238.18,240.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:242.18,244.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:249.52,257.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:257.10,266.5 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:269.18,271.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:276.21,278.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:278.17,280.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:286.88,288.16 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:293.2,293.16 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:296.2,296.8 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:288.16,290.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:290.8,292.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:293.16,295.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:300.55,309.16 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:313.2,316.48 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:319.2,319.23 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:309.16,311.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:316.48,318.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:325.67,327.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:331.2,332.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:336.2,336.15 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:327.16,329.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:332.16,334.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:341.67,343.51 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:347.2,347.17 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:343.51,345.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:365.69,367.2 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:369.118,383.2 8 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:385.97,388.21 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:392.2,392.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:396.2,396.13 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:388.21,391.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:392.21,395.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:400.93,407.39 4 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:415.2,418.12 3 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:407.39,410.3 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:410.8,412.3 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:426.101,444.2 8 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:445.158,450.60 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:457.2,457.50 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:462.2,462.31 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:476.2,476.12 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:450.60,454.3 3 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:457.50,459.3 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:462.31,464.17 2 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:467.3,467.31 1 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:464.17,466.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:467.31,468.33 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:469.28,470.71 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:471.37,472.74 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:480.151,483.16 2 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:488.2,489.16 2 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:493.2,493.28 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:499.2,499.61 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:508.2,508.16 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:515.2,524.60 4 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:627.2,627.50 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:632.2,632.31 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:658.2,658.12 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:483.16,485.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:489.16,491.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:493.28,497.3 3 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:499.61,503.25 1 11\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:503.25,505.4 1 11\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:508.16,509.25 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:509.25,511.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:524.60,533.78 9 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:536.3,542.36 5 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:549.3,555.24 3 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:564.3,564.30 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:569.3,570.25 2 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:573.3,573.25 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:583.3,583.62 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:588.3,588.50 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:591.3,591.72 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:594.3,598.83 3 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:605.3,605.74 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:612.3,612.29 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:615.3,615.31 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:619.3,619.84 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:623.3,623.13 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:533.78,535.4 1 23\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:542.36,544.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:544.18,546.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:555.24,556.29 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:556.30,558.5 0 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:558.10,560.5 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:564.30,566.4 1 11\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:570.25,572.4 1 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:573.25,575.18 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:575.18,577.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:577.10,579.5 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:583.62,585.4 1 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:588.50,590.4 1 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:591.72,593.4 1 11\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:598.83,600.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:600.9,602.4 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:605.74,607.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:607.9,609.4 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:612.29,614.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:615.31,617.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:619.84,621.4 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:627.50,629.3 1 23\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:632.31,634.17 2 73\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:637.3,637.31 1 73\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:634.17,636.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:637.31,638.33 1 49\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:639.28,640.71 1 7\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:641.37,642.74 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:643.29,645.35 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:648.5,649.47 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:654.5,654.63 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:645.35,646.11 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:649.47,653.6 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:662.64,664.36 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:667.2,667.11 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:664.36,666.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:672.75,673.21 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:676.2,676.22 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:679.2,679.11 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:673.21,675.3 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:676.22,678.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:693.151,696.58 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:706.2,706.27 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:696.58,698.20 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:698.20,703.4 4 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:710.90,712.52 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:727.2,727.64 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:741.2,741.8 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:712.52,715.28 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:719.3,719.28 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:723.3,723.63 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:715.28,717.4 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:719.28,721.4 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:727.64,730.34 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:734.3,734.34 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:738.3,738.68 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:730.34,732.4 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:734.34,736.4 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:745.70,746.16 1 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:757.2,757.16 1 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:747.10,747.10 0 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:748.16,749.29 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:750.15,751.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:752.22,753.35 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:754.10,755.88 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:761.72,762.17 1 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:763.27,764.38 1 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:765.20,766.37 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:767.20,768.41 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:769.10,770.86 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:777.64,780.28 2 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:787.2,789.13 3 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:780.28,781.63 1 119\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:781.63,783.4 1 23\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:783.9,785.4 1 96\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:796.63,799.28 3 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:813.2,813.16 1 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:799.28,800.40 1 119\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:800.40,802.16 2 119\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:802.16,804.13 2 5\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:805.10,808.5 2 114\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:809.9,811.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:817.63,819.49 2 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:822.2,823.19 2 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:819.49,821.3 1 34\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:827.56,828.13 1 5\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:831.2,832.16 2 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:835.2,836.16 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:828.13,830.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:832.16,834.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:840.90,843.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:846.2,850.16 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:854.2,854.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:843.16,845.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:850.16,852.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:858.54,860.16 2 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:863.2,863.31 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:860.16,862.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:867.40,872.2 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:875.41,883.2 2 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:886.46,889.2 2 33\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:891.61,893.36 2 40\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:896.2,896.13 1 40\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:893.36,895.3 1 33\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/k8sutils.go:900.45,902.2 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:75.121,79.61 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:104.2,104.18 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:79.61,84.32 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:84.32,86.69 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:86.69,87.38 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:87.38,90.75 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:97.6,99.37 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:90.75,91.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:91.27,93.16 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:108.92,109.17 1 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:112.2,120.22 2 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:127.2,127.12 1 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:109.17,111.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:120.22,126.3 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:131.117,135.40 3 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:176.2,187.35 2 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:194.2,194.12 1 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:135.40,138.19 3 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:142.3,147.17 5 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:152.3,157.24 2 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:162.3,173.35 3 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:138.19,141.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:147.17,150.12 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:157.24,160.4 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:187.35,193.3 1 8\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:200.87,216.2 2 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:219.114,221.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:227.2,242.18 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:221.16,223.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:248.135,262.16 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:266.2,266.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:294.2,294.23 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:262.16,264.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:267.20,269.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:273.3,273.30 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:283.3,283.40 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:285.24,291.4 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:269.17,271.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:273.30,274.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:274.21,277.19 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:280.5,280.32 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:277.19,279.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:299.46,300.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:303.2,303.45 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:306.2,306.13 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:300.27,302.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:303.45,305.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:309.74,313.25 3 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:322.2,323.32 2 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:313.25,315.13 2 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:315.13,317.4 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:317.9,319.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:327.120,329.16 2 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:333.2,334.54 2 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:339.2,352.18 4 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:329.16,331.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:334.54,335.33 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:335.33,337.4 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:356.105,358.30 2 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:364.2,392.19 5 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:408.2,408.11 1 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:358.30,360.3 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:360.8,362.3 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:392.19,398.29 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:401.3,402.35 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:405.3,405.99 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:398.29,400.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:402.35,404.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:412.91,429.2 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:431.107,433.30 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:438.2,459.11 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:433.30,435.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:435.8,437.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:462.112,481.29 5 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:511.2,511.36 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:528.2,528.16 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:481.29,483.14 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:486.3,506.21 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:483.14,485.4 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:506.21,509.4 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:511.36,512.41 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:512.41,519.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:519.9,525.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:532.96,534.50 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:559.2,559.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:534.50,535.24 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:535.24,537.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:541.4,554.37 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:537.18,540.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:555.9,557.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:563.154,565.16 2 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:569.2,587.28 2 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:593.2,593.18 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:599.2,599.31 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:603.2,603.17 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:565.16,567.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:587.28,591.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:593.18,595.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:595.8,597.3 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:599.31,601.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:607.69,610.36 3 38\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:626.2,626.14 1 38\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:610.36,611.23 1 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:614.3,619.75 2 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:622.3,623.26 2 31\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:611.23,612.12 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:619.75,621.4 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:629.113,632.36 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:654.2,654.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:632.36,633.25 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:636.3,646.75 5 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:633.25,635.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:646.75,649.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:649.9,652.4 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:658.90,663.36 4 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:700.2,700.21 1 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:663.36,664.25 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:668.3,674.49 5 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:682.3,688.90 2 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:693.3,693.75 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:697.3,698.45 2 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:664.25,666.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:674.49,676.66 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:679.4,679.69 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:676.66,678.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:688.90,690.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:693.75,695.4 1 25\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:704.74,707.40 3 34\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:710.2,710.42 1 34\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:713.2,716.3 1 34\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:707.40,709.3 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:710.42,712.3 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:720.112,725.43 3 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:746.2,746.30 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:725.43,745.3 7 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:755.120,758.30 3 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:826.2,826.30 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:758.30,759.48 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:759.48,760.30 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:763.4,763.30 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:767.4,770.33 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:798.4,808.32 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:813.4,823.49 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:760.30,762.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:763.30,765.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:770.33,775.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:775.10,781.40 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:790.5,790.61 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:795.5,795.24 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:781.40,784.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:784.11,787.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:790.61,793.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:808.32,811.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:830.169,842.33 9 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:847.2,847.57 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:857.2,863.41 5 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:957.2,957.46 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:842.33,844.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:847.57,848.41 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:851.3,853.35 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:848.41,850.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:863.41,866.30 2 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:883.3,893.22 3 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:943.3,952.62 4 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:866.30,867.23 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:878.4,879.11 2 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:867.23,869.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:869.10,869.26 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:869.26,871.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:871.10,871.27 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:871.27,873.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:873.10,875.5 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:880.9,882.4 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:893.22,895.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:895.9,895.25 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:895.25,897.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:900.4,900.22 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:897.18,899.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:901.9,901.26 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:901.26,904.99 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:904.99,906.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:906.10,910.28 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:910.28,912.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:914.9,916.26 2 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:916.26,919.35 3 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:922.5,922.32 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:934.5,936.19 2 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:940.5,940.36 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:919.35,921.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:922.32,924.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:924.11,925.45 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:925.45,926.39 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:926.39,928.8 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:928.13,928.60 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:928.60,930.8 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:936.19,938.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:952.62,954.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:962.76,964.20 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:971.2,973.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:964.20,968.3 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:977.121,980.25 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:997.2,999.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:980.25,982.26 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:985.3,985.32 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:988.3,995.4 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:982.26,984.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:985.32,987.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1003.89,1005.16 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1008.2,1009.27 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1013.2,1015.8 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1005.16,1007.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1009.27,1011.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1019.90,1026.2 1 17\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1029.98,1037.30 3 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1067.2,1067.40 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1079.2,1080.18 2 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1037.30,1040.40 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1040.40,1045.18 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1050.4,1050.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1045.18,1047.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1050.27,1062.5 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1067.40,1068.31 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1068.31,1073.4 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1084.66,1090.68 4 33\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1103.2,1103.17 1 33\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1090.68,1102.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1107.100,1112.36 3 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1117.2,1117.50 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1130.2,1130.20 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1112.36,1115.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1117.50,1128.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1133.118,1136.25 3 66\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1139.2,1139.31 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1147.2,1147.11 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1136.25,1138.3 1 64\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1139.31,1146.3 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1151.145,1155.51 3 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1162.2,1162.36 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1173.2,1173.64 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1183.2,1183.30 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1187.2,1187.59 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1191.2,1191.59 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1195.2,1195.47 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1199.2,1199.30 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1206.2,1206.16 1 30\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1155.51,1157.3 1 21\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1157.8,1159.3 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1162.36,1164.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1164.27,1167.4 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1167.9,1167.43 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1167.43,1169.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1173.64,1177.27 4 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1180.3,1180.23 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1177.27,1179.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1183.30,1185.3 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1187.59,1189.3 1 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1191.59,1193.3 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1195.47,1197.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1199.30,1200.43 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1200.43,1203.4 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1209.142,1210.41 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1220.2,1220.16 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1210.41,1213.41 3 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1216.3,1218.39 3 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1213.41,1214.12 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1224.83,1238.2 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1241.99,1267.2 3 36\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1269.102,1275.74 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1299.2,1299.12 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1275.74,1277.26 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1281.3,1281.26 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1285.3,1289.17 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1294.3,1295.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1277.26,1279.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1281.26,1283.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1289.17,1291.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1295.17,1297.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1302.131,1303.27 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1303.27,1304.44 1 19\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1304.44,1306.29 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1309.4,1309.21 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1306.29,1308.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1309.21,1311.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1312.9,1315.35 3 19\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1315.35,1317.5 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1319.8,1320.40 1 13\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1320.40,1323.4 2 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1323.9,1325.4 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1329.129,1330.30 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1341.2,1341.12 1 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1330.30,1331.39 1 18\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1331.39,1335.18 3 36\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1338.4,1338.35 1 36\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1335.18,1337.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1346.123,1350.34 2 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1359.2,1359.32 1 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1466.2,1467.34 2 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1509.2,1513.24 3 29\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1350.34,1352.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1355.3,1355.32 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1352.17,1354.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1355.32,1357.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1359.32,1362.69 3 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1362.69,1367.40 3 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1381.4,1383.34 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1463.4,1463.47 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1367.40,1368.35 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1368.35,1370.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1370.11,1372.32 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1375.6,1375.37 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1372.32,1374.7 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1383.34,1386.32 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1394.5,1398.73 4 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1402.5,1407.19 4 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1411.5,1411.31 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1416.5,1421.19 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1430.5,1430.19 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1436.5,1449.86 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1453.5,1454.19 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1458.5,1458.91 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1386.32,1388.24 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1391.6,1391.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1388.24,1390.7 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1398.73,1400.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1407.19,1409.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1411.31,1415.6 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1421.19,1425.28 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1425.28,1427.7 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1430.19,1431.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1431.28,1433.7 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1449.86,1451.6 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1454.19,1456.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1458.91,1460.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1467.34,1471.22 2 32\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1475.3,1479.63 3 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1484.3,1484.93 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1492.3,1492.48 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1495.3,1498.17 3 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1502.3,1502.82 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1505.3,1505.46 1 26\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1471.22,1472.12 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1479.63,1481.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1484.93,1488.4 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1488.9,1490.4 1 24\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1492.48,1494.4 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1498.17,1500.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1502.82,1504.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1517.162,1518.25 1 88\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1557.2,1557.12 1 88\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1519.26,1521.17 2 27\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1524.3,1524.28 1 27\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1525.25,1527.17 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1530.3,1530.28 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1531.27,1533.17 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1536.3,1536.28 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1537.35,1539.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1542.3,1542.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1543.16,1549.17 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1552.3,1553.30 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1554.29,1555.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1521.17,1523.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1527.17,1529.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1533.17,1535.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1539.17,1541.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/kubernetes.go:1549.17,1551.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:22.92,23.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:23.32,27.18 3 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:31.3,32.17 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:36.3,49.45 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:27.18,29.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:32.17,33.41 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:53.94,54.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:54.32,56.36 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:56.36,58.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:58.18,60.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:66.67,67.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:67.32,68.53 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:68.53,71.29 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:75.4,75.29 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:79.4,79.38 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:71.29,73.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:75.29,77.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:79.38,81.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:87.69,88.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:88.32,89.65 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:89.65,92.35 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:96.4,96.35 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:100.4,100.38 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:92.35,94.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:96.35,98.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:100.38,102.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:108.80,109.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:109.32,114.24 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:123.3,123.30 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:128.3,129.25 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:132.3,132.25 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:142.3,145.62 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:150.3,150.50 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:153.3,153.72 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:114.24,115.29 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:115.30,117.5 0 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:117.10,119.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:123.30,125.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:129.25,131.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:132.25,134.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:134.18,136.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:136.10,138.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:145.62,147.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:150.50,152.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:153.72,155.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:159.54,161.33 2 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:164.2,164.12 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:161.33,163.3 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:167.53,168.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:168.32,171.81 3 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:171.81,172.35 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:172.35,173.38 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:173.38,175.11 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:182.69,184.43 2 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:188.2,188.12 1 15\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:184.43,186.3 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:191.68,192.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:192.32,194.37 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:194.37,196.97 2 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:196.97,197.46 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:197.46,198.54 1 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:198.54,200.12 2 4\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:209.60,210.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:210.32,214.37 2 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:214.37,215.63 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:215.63,217.5 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:223.80,224.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:224.32,225.83 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:225.83,226.14 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:227.9,228.38 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:228.38,230.5 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:236.78,237.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:237.32,238.74 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:238.74,239.14 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:240.9,242.4 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:246.60,247.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:247.32,249.29 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:249.29,251.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:255.62,256.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:256.32,257.31 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:257.31,259.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:263.62,266.82 2 66\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:270.2,270.31 1 14\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:293.2,300.15 5 14\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:266.82,268.3 1 52\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:270.31,276.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:276.8,276.111 1 12\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:276.111,283.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:283.8,283.59 1 10\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:283.59,289.3 1 10\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:289.8,290.59 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:303.66,304.32 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:304.32,306.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:309.77,310.32 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:310.32,312.3 1 6\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:315.63,316.29 1 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:319.2,319.16 1 20\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:316.29,318.3 1 80\ngithub.com/kubernetes/kompose/pkg/transformer/kubernetes/podspec.go:322.43,324.2 1 9\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:55.131,56.25 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:62.2,63.28 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:67.2,69.56 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:80.2,93.11 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:56.25,58.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:63.28,65.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:69.56,78.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:96.125,99.51 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:108.2,109.16 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:113.2,151.16 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:99.51,100.26 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:103.3,103.76 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:100.26,102.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:109.16,111.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:155.128,162.33 3 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:166.2,167.30 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:173.2,214.19 3 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:222.2,222.11 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:162.33,164.3 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:167.30,169.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:169.8,171.3 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:214.19,220.3 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:225.103,248.37 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:251.2,251.14 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:248.37,250.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:256.122,258.36 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:262.2,268.34 6 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:278.2,279.34 2 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:417.2,421.24 3 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:258.36,260.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:268.34,270.17 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:273.3,273.32 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:270.17,272.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:273.32,275.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:279.34,285.52 4 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:292.3,292.37 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:300.3,300.75 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:324.3,324.65 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:386.3,386.28 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:408.3,409.17 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:413.3,413.46 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:285.52,287.4 1 3\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:287.9,289.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:292.37,294.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:300.75,302.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:306.4,306.27 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:311.4,312.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:317.4,318.18 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:302.27,304.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:306.27,308.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:312.18,314.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:318.18,320.5 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:324.65,326.34 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:329.4,330.34 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:326.34,328.5 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:331.9,334.34 2 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:342.4,342.58 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:334.34,338.5 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:342.58,345.19 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:351.5,351.66 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:356.5,356.26 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:364.5,364.28 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:375.5,376.19 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:379.5,382.77 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:345.19,347.14 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:351.66,353.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:356.26,358.20 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:358.20,360.7 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:364.28,365.20 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:368.6,369.20 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:365.20,367.7 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:369.20,371.7 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:376.19,378.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:386.28,387.45 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:387.45,389.30 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:392.5,392.22 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:389.30,391.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:392.22,394.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:395.10,399.36 3 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:399.36,401.6 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:403.9,403.47 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:403.47,406.4 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/openshift.go:409.17,411.4 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:10.39,22.17 3 7\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:26.2,27.17 2 7\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:30.2,30.17 1 5\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:22.17,24.3 1 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:27.17,29.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:34.57,38.16 4 6\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:42.2,43.24 2 4\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:38.16,40.3 1 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:47.26,50.2 2 0\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:53.68,57.16 4 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:60.2,61.37 2 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:64.2,64.17 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:57.16,59.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:61.37,63.3 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:68.65,72.16 4 2\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:75.2,75.50 1 1\ngithub.com/kubernetes/kompose/pkg/transformer/openshift/utils.go:72.16,74.3 1 1\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:42.114,47.16 3 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:50.2,54.16 3 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:59.2,60.16 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:65.2,78.16 5 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:82.2,84.12 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:47.16,49.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:54.16,56.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:60.16,62.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/build.go:78.16,80.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/client.go:26.39,34.25 3 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/client.go:43.2,43.16 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/client.go:47.2,47.20 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/client.go:34.25,38.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/client.go:38.8,42.3 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/client.go:43.16,45.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:36.63,45.2 1 4\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:50.77,57.16 3 4\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:62.2,62.26 1 4\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:71.2,73.19 2 4\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:57.16,59.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:62.26,66.17 3 2\ngithub.com/kubernetes/kompose/pkg/utils/docker/image.go:66.17,68.4 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:37.45,53.16 5 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:60.2,61.9 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:70.2,72.16 3 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:77.2,79.12 3 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:53.16,55.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:55.8,57.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:61.9,68.3 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:72.16,75.3 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:88.63,92.64 3 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/push.go:92.64,94.3 1 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/tag.go:30.43,38.16 4 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/tag.go:43.2,44.12 2 0\ngithub.com/kubernetes/kompose/pkg/utils/docker/tag.go:38.16,41.3 2 0\n"
  },
  {
    "path": "index.md",
    "content": "---\nlayout: default\n---\n\n# Kubernetes + Compose = Kompose\n\n## A conversion tool to go from Compose to Kubernetes\n\n### What's Kompose?\n\nKompose is a conversion tool for Compose to container orchestrators such as Kubernetes (or OpenShift).\n\nWhy do developers love it?\n\n- Simplify your development process with Compose and then deploy your containers to a production cluster\n- Convert your `docker-compose.yaml` with one simple command `kompose convert`\n\n### It's as simple as 1-2-3\n\n1. [Use an example docker-compose.yaml file](https://raw.githubusercontent.com/kubernetes/kompose/master/examples/docker-compose-v3.yaml) or your own\n2. Run `kompose convert`\n3. Run `kubectl apply` and check your Kubernetes cluster for your newly deployed containers!\n\n```sh\n$ wget https://raw.githubusercontent.com/kubernetes/kompose/master/examples/docker-compose-v3.yaml -O docker-compose.yaml\n\n$ kompose convert\n\n$ kubectl apply -f .\n\n$ kubectl get po\nNAME                            READY     STATUS              RESTARTS   AGE\nfrontend-591253677-5t038        1/1       Running             0          10s\nredis-master-2410703502-9hshf   1/1       Running             0          10s\nredis-replica-4049176185-hr1lr  1/1       Running             0          10s\n```\n\nA more detailed guide is available in our [getting started guide](/docs/getting-started.md).\n\n### Install Kompose on Linux, macOS or Windows\n\nGrab the Kompose binary!\n\n```sh\n# Linux\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.25.0/kompose-linux-amd64 -o kompose\n\n# macOS\ncurl -L https://github.com/kubernetes/kompose/releases/download/v1.25.0/kompose-darwin-amd64 -o kompose\n\nchmod +x kompose\nsudo mv ./kompose /usr/local/bin/kompose\n```\n\n_Windows:_ Download from [GitHub](https://github.com/kubernetes/kompose/releases/download/v1.25.0/kompose-windows-amd64.exe) and add the binary to your PATH.\n"
  },
  {
    "path": "main.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/kubernetes/kompose/cmd\"\n)\n\nfunc main() {\n\tif err := cmd.Execute(); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "pkg/app/app.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage app\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\n\t\"os\"\n\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/loader\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\t\"github.com/kubernetes/kompose/pkg/transformer/kubernetes\"\n\t\"github.com/kubernetes/kompose/pkg/transformer/openshift\"\n)\n\nvar (\n\t// DefaultComposeFiles is a list of filenames that kompose will use if no file is explicitly set\n\tDefaultComposeFiles = []string{\n\t\t\"compose.yaml\",\n\t\t\"compose.yml\",\n\t\t\"docker-compose.yaml\",\n\t\t\"docker-compose.yml\",\n\t}\n)\n\nconst (\n\t// ProviderKubernetes is provider kubernetes\n\tProviderKubernetes = \"kubernetes\"\n\t// ProviderOpenshift is provider openshift\n\tProviderOpenshift = \"openshift\"\n\t// DefaultProvider - provider that will be used if there is no provider was explicitly set\n\tDefaultProvider = ProviderKubernetes\n)\n\nvar inputFormat = \"compose\"\n\n// ValidateFlags validates all command line flags\nfunc ValidateFlags(args []string, cmd *cobra.Command, opt *kobject.ConvertOptions) {\n\tif opt.OutFile == \"-\" {\n\t\topt.ToStdout = true\n\t\topt.OutFile = \"\"\n\t}\n\n\t// Get the provider\n\tprovider := cmd.Flags().Lookup(\"provider\").Value.String()\n\tlog.Debugf(\"Checking validation of provider: %s\", provider)\n\n\t// OpenShift specific flags\n\tdeploymentConfig := cmd.Flags().Lookup(\"deployment-config\").Changed\n\tbuildRepo := cmd.Flags().Lookup(\"build-repo\").Changed\n\tbuildBranch := cmd.Flags().Lookup(\"build-branch\").Changed\n\n\t// Kubernetes specific flags\n\tchart := cmd.Flags().Lookup(\"chart\").Changed\n\tdaemonSet := cmd.Flags().Lookup(\"daemon-set\").Changed\n\treplicationController := cmd.Flags().Lookup(\"replication-controller\").Changed\n\tdeployment := cmd.Flags().Lookup(\"deployment\").Changed\n\n\t// Get the controller\n\tcontroller := opt.Controller\n\tlog.Debugf(\"Checking validation of controller: %s\", controller)\n\n\t// Check validations against provider flags\n\tswitch {\n\tcase provider == ProviderOpenshift:\n\t\tif chart {\n\t\t\tlog.Fatalf(\"--chart, -c is a Kubernetes only flag\")\n\t\t}\n\t\tif daemonSet {\n\t\t\tlog.Fatalf(\"--daemon-set is a Kubernetes only flag\")\n\t\t}\n\t\tif replicationController {\n\t\t\tlog.Fatalf(\"--replication-controller is a Kubernetes only flag\")\n\t\t}\n\t\tif deployment {\n\t\t\tlog.Fatalf(\"--deployment, -d is a Kubernetes only flag\")\n\t\t}\n\t\tif controller == \"daemonset\" || controller == \"replicationcontroller\" || controller == \"deployment\" {\n\t\t\tlog.Fatalf(\"--controller= daemonset, replicationcontroller or deployment is a Kubernetes only flag\")\n\t\t}\n\tcase provider == ProviderKubernetes:\n\t\tif deploymentConfig {\n\t\t\tlog.Fatalf(\"--deployment-config is an OpenShift only flag\")\n\t\t}\n\t\tif buildRepo {\n\t\t\tlog.Fatalf(\"--build-repo is an Openshift only flag\")\n\t\t}\n\t\tif buildBranch {\n\t\t\tlog.Fatalf(\"--build-branch is an Openshift only flag\")\n\t\t}\n\t\tif controller == \"deploymentconfig\" {\n\t\t\tlog.Fatalf(\"--controller=deploymentConfig is an OpenShift only flag\")\n\t\t}\n\t}\n\n\t// Standard checks regardless of provider\n\tif len(opt.OutFile) != 0 && opt.ToStdout {\n\t\tlog.Fatalf(\"Error: --out and --stdout can't be set at the same time\")\n\t}\n\n\tif opt.CreateChart && opt.ToStdout {\n\t\tlog.Fatalf(\"Error: chart cannot be generated when --stdout is specified\")\n\t}\n\n\tif opt.Replicas < 0 {\n\t\tlog.Fatalf(\"Error: --replicas cannot be negative\")\n\t}\n\n\tif len(args) != 0 {\n\t\tlog.Fatal(\"Unknown Argument(s): \", strings.Join(args, \",\"))\n\t}\n\n\tif opt.GenerateJSON && opt.GenerateYaml {\n\t\tlog.Fatalf(\"YAML and JSON format cannot be provided at the same time\")\n\t}\n\n\tif _, ok := kubernetes.ValidVolumeSet[opt.Volumes]; !ok {\n\t\tvalidVolumesTypes := make([]string, 0)\n\t\tfor validVolumeType := range kubernetes.ValidVolumeSet {\n\t\t\tvalidVolumesTypes = append(validVolumesTypes, fmt.Sprintf(\"'%s'\", validVolumeType))\n\t\t}\n\t\tlog.Fatal(\"Unknown Volume type: \", opt.Volumes, \", possible values are: \", strings.Join(validVolumesTypes, \" \"))\n\t}\n}\n\n// ValidateComposeFile validates the compose file provided for conversion\nfunc ValidateComposeFile(opt *kobject.ConvertOptions) error {\n\tif len(opt.InputFiles) == 0 {\n\t\t// Go through a range of \"default\" file names to see if tany ofthem exist in the current directory\n\t\tfor _, name := range DefaultComposeFiles {\n\t\t\t_, err := os.Stat(name)\n\t\t\tif err != nil {\n\t\t\t\tlog.Debugf(\"'%s' not found: %v\", name, err)\n\t\t\t} else {\n\t\t\t\topt.InputFiles = []string{name}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\t// Return an error message that no compose or docker-compose yaml files were found\n\t\treturn fmt.Errorf(\"No compose or docker-compose yaml file found in the current directory\")\n\t}\n\treturn nil\n}\n\nfunc validateControllers(opt *kobject.ConvertOptions) {\n\tsingleOutput := len(opt.OutFile) != 0 || opt.OutFile == \"-\" || opt.ToStdout\n\tif opt.Provider == ProviderKubernetes {\n\t\t// create deployment by default if no controller has been set\n\t\tif !opt.CreateD && !opt.CreateDS && !opt.CreateRC && opt.Controller == \"\" {\n\t\t\topt.CreateD = true\n\t\t}\n\t\tif singleOutput {\n\t\t\tcount := 0\n\t\t\tif opt.CreateD {\n\t\t\t\tcount++\n\t\t\t}\n\t\t\tif opt.CreateDS {\n\t\t\t\tcount++\n\t\t\t}\n\t\t\tif opt.CreateRC {\n\t\t\t\tcount++\n\t\t\t}\n\t\t\tif count > 1 {\n\t\t\t\tlog.Fatalf(\"Error: only one kind of Kubernetes resource can be generated when --out or --stdout is specified\")\n\t\t\t}\n\t\t}\n\t} else if opt.Provider == ProviderOpenshift {\n\t\t// create deploymentconfig by default if no controller has been set\n\t\tif !opt.CreateDeploymentConfig {\n\t\t\topt.CreateDeploymentConfig = true\n\t\t}\n\t\tif singleOutput {\n\t\t\tcount := 0\n\t\t\tif opt.CreateDeploymentConfig {\n\t\t\t\tcount++\n\t\t\t}\n\t\t\t// Add more controllers here once they are available in OpenShift\n\t\t\t// if opt.foo {count++}\n\n\t\t\tif count > 1 {\n\t\t\t\tlog.Fatalf(\"Error: only one kind of OpenShift resource can be generated when --out or --stdout is specified\")\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Convert transforms docker compose or dab file to k8s objects\nfunc Convert(opt kobject.ConvertOptions) ([]runtime.Object, error) {\n\tvalidateControllers(&opt)\n\n\t// loader parses input from file into komposeObject.\n\tl, err := loader.GetLoader(inputFormat)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: make(map[string]kobject.ServiceConfig),\n\t}\n\tkomposeObject, err = l.LoadFile(opt.InputFiles, opt.Profiles, opt.NoInterpolate)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tkomposeObject.Namespace = opt.Namespace\n\n\t// Get the directory of the compose file\n\tworkDir, err := transformer.GetComposeFileDir(opt.InputFiles)\n\tif err != nil {\n\t\tlog.Fatalf(\"Unable to get compose file directory: %s\", err)\n\t}\n\n\t// convert env_file from absolute to relative path\n\tfor _, service := range komposeObject.ServiceConfigs {\n\t\tif len(service.EnvFile) <= 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor i, envFile := range service.EnvFile {\n\t\t\tif !filepath.IsAbs(envFile) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\trelPath, err := filepath.Rel(workDir, envFile)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\n\t\t\tservice.EnvFile[i] = filepath.ToSlash(relPath)\n\t\t}\n\t}\n\n\t// Get a transformer that maps komposeObject to provider's primitives\n\tt := getTransformer(opt)\n\n\t// Do the transformation\n\tobjects, err := t.Transform(komposeObject, opt)\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Print output\n\terr = kubernetes.PrintList(objects, opt)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\treturn objects, err\n}\n\n// Convenience method to return the appropriate Transformer based on\n// what provider we are using.\nfunc getTransformer(opt kobject.ConvertOptions) transformer.Transformer {\n\tvar t transformer.Transformer\n\tif opt.Provider == DefaultProvider {\n\t\t// Create/Init new Kubernetes object with CLI opts\n\t\tt = &kubernetes.Kubernetes{Opt: opt}\n\t} else {\n\t\t// Create/Init new OpenShift object that is initialized with a newly\n\t\t// created Kubernetes object. Openshift inherits from Kubernetes\n\t\tt = &openshift.OpenShift{Kubernetes: kubernetes.Kubernetes{Opt: opt}}\n\t}\n\treturn t\n}\n"
  },
  {
    "path": "pkg/kobject/kobject.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage kobject\n\nimport (\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\tdeployapi \"github.com/openshift/api/apps/v1\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/spf13/cast\"\n\tv1 \"k8s.io/api/apps/v1\"\n\tbatchv1 \"k8s.io/api/batch/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\n// KomposeObject holds the generic struct of Kompose transformation\ntype KomposeObject struct {\n\tServiceConfigs map[string]ServiceConfig\n\t// LoadedFrom is name of the loader that created KomposeObject\n\t// Transformer need to know origin format in order to tell user what tag is not supported in origin format\n\t// as they can have different names. For example environment variables  are called environment in compose but Env in bundle.\n\tLoadedFrom string\n\n\tSecrets types.Secrets\n\n\t// Namespace is the namespace where all the generated objects would be assigned to\n\tNamespace string\n}\n\n// ConvertOptions holds all options that controls transformation process\ntype ConvertOptions struct {\n\tToStdout                    bool\n\tCreateD                     bool\n\tCreateRC                    bool\n\tCreateDS                    bool\n\tCreateDeploymentConfig      bool\n\tBuildRepo                   string\n\tBuildBranch                 string\n\tBuild                       string\n\tProfiles                    []string\n\tPushImage                   bool\n\tPushImageRegistry           string\n\tCreateChart                 bool\n\tGenerateYaml                bool\n\tGenerateJSON                bool\n\tStoreManifest               bool\n\tEmptyVols                   bool\n\tVolumes                     string\n\tPVCRequestSize              string\n\tInsecureRepository          bool\n\tReplicas                    int\n\tInputFiles                  []string\n\tOutFile                     string\n\tProvider                    string\n\tNamespace                   string\n\tController                  string\n\tIsDeploymentFlag            bool\n\tIsDaemonSetFlag             bool\n\tIsReplicationControllerFlag bool\n\tIsReplicaSetFlag            bool\n\tIsDeploymentConfigFlag      bool\n\tIsNamespaceFlag             bool\n\n\tBuildCommand string\n\tPushCommand  string\n\n\tServer string\n\n\tYAMLIndent int\n\n\tWithKomposeAnnotation bool\n\n\tMultipleContainerMode   bool\n\tServiceGroupMode        string\n\tServiceGroupName        string\n\tSecretsAsFiles          bool\n\tGenerateNetworkPolicies bool\n\tNoInterpolate           bool\n}\n\n// IsPodController indicate if the user want to use a controller\nfunc (opt *ConvertOptions) IsPodController() bool {\n\treturn opt.IsDeploymentFlag || opt.IsDaemonSetFlag || opt.IsReplicationControllerFlag || opt.Controller != \"\"\n}\n\n// ServiceConfigGroup holds an array of a ServiceConfig objects.\ntype ServiceConfigGroup []ServiceConfig\n\n// ServiceConfig holds the basic struct of a container\n// which should not introduce any kubernetes specific struct\ntype ServiceConfig struct {\n\tName                          string\n\tContainerName                 string\n\tImage                         string             `compose:\"image\"`\n\tEnvironment                   []EnvVar           `compose:\"environment\"`\n\tEnvFile                       []string           `compose:\"env_file\"`\n\tPort                          []Ports            `compose:\"ports\"`\n\tCommand                       []string           `compose:\"command\"`\n\tWorkingDir                    string             `compose:\"\"`\n\tDomainName                    string             `compose:\"domainname\"`\n\tHostName                      string             `compose:\"hostname\"`\n\tReadOnly                      bool               `compose:\"read_only\"`\n\tArgs                          []string           `compose:\"args\"`\n\tVolList                       []string           `compose:\"volumes\"`\n\tNetworkMode                   string             `compose:\"network_mode\"`\n\tNetwork                       []string           `compose:\"network\"`\n\tLabels                        map[string]string  `compose:\"labels\"`\n\tAnnotations                   map[string]string  `compose:\"\"`\n\tCPUSet                        string             `compose:\"cpuset\"`\n\tCPUShares                     int64              `compose:\"cpu_shares\"`\n\tCPUQuota                      int64              `compose:\"cpu_quota\"`\n\tCPULimit                      int64              `compose:\"\"`\n\tCPUReservation                int64              `compose:\"\"`\n\tCapAdd                        []string           `compose:\"cap_add\"`\n\tCapDrop                       []string           `compose:\"cap_drop\"`\n\tExpose                        []string           `compose:\"expose\"`\n\tImagePullPolicy               string             `compose:\"kompose.image-pull-policy\"`\n\tPid                           string             `compose:\"pid\"`\n\tPrivileged                    bool               `compose:\"privileged\"`\n\tRestart                       string             `compose:\"restart\"`\n\tUser                          string             `compose:\"user\"`\n\tVolumesFrom                   []string           `compose:\"volumes_from\"`\n\tServiceType                   string             `compose:\"kompose.service.type\"`\n\tServiceExternalTrafficPolicy  string             `compose:\"kompose.service.external-traffic-policy\"`\n\tNodePortPort                  int32              `compose:\"kompose.service.nodeport.port\"`\n\tStopGracePeriod               string             `compose:\"stop_grace_period\"`\n\tBuild                         string             `compose:\"build\"`\n\tBuildArgs                     map[string]*string `compose:\"build-args\"`\n\tExposeContainerToHost         bool               `compose:\"kompose.controller.port.expose\"`\n\tExposeService                 string             `compose:\"kompose.service.expose\"`\n\tExposeServicePath             string             `compose:\"kompose.service.expose.path\"`\n\tBuildLabels                   map[string]string  `compose:\"build-labels\"`\n\tBuildTarget                   string             `compose:\"\"`\n\tExposeServiceTLS              string             `compose:\"kompose.service.expose.tls-secret\"`\n\tExposeServiceIngressClassName string             `compose:\"kompose.service.expose.ingress-class-name\"`\n\tImagePullSecret               string             `compose:\"kompose.image-pull-secret\"`\n\tStdin                         bool               `compose:\"stdin_open\"`\n\tTty                           bool               `compose:\"tty\"`\n\tMemLimit                      types.UnitBytes    `compose:\"mem_limit\"`\n\tMemReservation                types.UnitBytes    `compose:\"\"`\n\tDeployMode                    string             `compose:\"\"`\n\tVolumeMountSubPath            string             `compose:\"kompose.volume.subpath\"`\n\t// DeployLabels mapping to kubernetes labels\n\tDeployLabels             map[string]string         `compose:\"\"`\n\tDeployUpdateConfig       types.UpdateConfig        `compose:\"\"`\n\tTmpFs                    []string                  `compose:\"tmpfs\"`\n\tDockerfile               string                    `compose:\"dockerfile\"`\n\tReplicas                 int                       `compose:\"replicas\"`\n\tGroupAdd                 []int64                   `compose:\"group_add\"`\n\tFsGroup                  int64                     `compose:\"kompose.security-context.fsgroup\"`\n\tCronJobSchedule          string                    `compose:\"kompose.cronjob.schedule\"`\n\tCronJobConcurrencyPolicy batchv1.ConcurrencyPolicy `compose:\"kompose.cronjob.concurrency_policy\"`\n\tCronJobBackoffLimit      *int32                    `compose:\"kompose.cronjob.backoff_limit\"`\n\tVolumes                  []Volumes                 `compose:\"\"`\n\tSecrets                  []types.ServiceSecretConfig\n\tHealthChecks             HealthChecks `compose:\"\"`\n\tPlacement                Placement    `compose:\"\"`\n\t//This is for long LONG SYNTAX link(https://docs.docker.com/compose/compose-file/#long-syntax)\n\tConfigs []types.ServiceConfigObjConfig `compose:\"\"`\n\t//This is for SHORT SYNTAX link(https://docs.docker.com/compose/compose-file/#configs)\n\tConfigsMetaData types.Configs `compose:\"\"`\n\n\tWithKomposeAnnotation bool `compose:\"\"`\n\tInGroup               bool\n}\n\n// HealthChecks used to distinguish between liveness and readiness\ntype HealthChecks struct {\n\tLiveness  HealthCheck\n\tReadiness HealthCheck\n}\n\n// HealthCheck the healthcheck configuration for a service\n// \"StartPeriod\" was added to v3.4 of the compose, see:\n// https://github.com/docker/cli/issues/116\ntype HealthCheck struct {\n\tTest        []string\n\tTimeout     int32\n\tInterval    int32\n\tRetries     int32\n\tStartPeriod int32\n\tDisable     bool\n\tHTTPPath    string\n\tHTTPPort    int32\n\tTCPPort     int32\n}\n\n// EnvVar holds the environment variable struct of a container\ntype EnvVar struct {\n\tName  string\n\tValue string\n}\n\n// Ports holds the ports struct of a container\ntype Ports struct {\n\tHostPort      int32\n\tContainerPort int32\n\tHostIP        string\n\tProtocol      string // Upper string\n}\n\n// ID returns an unique id for this port settings, to avoid conflict\nfunc (port *Ports) ID() string {\n\treturn strconv.Itoa(int(port.ContainerPort)) + port.Protocol\n}\n\n// Volumes holds the volume struct of container\ntype Volumes struct {\n\tSvcName       string // Service name to which volume is linked\n\tMountPath     string // Mountpath extracted from docker-compose file\n\tVFrom         string // denotes service name from which volume is coming\n\tVolumeName    string // name of volume if provided explicitly\n\tHost          string // host machine address\n\tContainer     string // Mountpath\n\tMode          string // access mode for volume\n\tPVCName       string // name of PVC\n\tPVCSize       string // PVC size\n\tSelectorValue string // Value of the label selector\n}\n\n// Placement holds the placement struct of container\ntype Placement struct {\n\tPositiveConstraints map[string]string\n\tNegativeConstraints map[string]string\n\tPreferences         []string\n}\n\n// GetConfigMapKeyFromMeta ...\n// given a source name ,find the file and extract the filename which will be act as ConfigMap key\n// return \"\" if not found\nfunc (s *ServiceConfig) GetConfigMapKeyFromMeta(name string) (string, error) {\n\tif s.ConfigsMetaData == nil {\n\t\treturn \"\", errors.Errorf(\"config %s not found\", name)\n\t}\n\tif _, ok := s.ConfigsMetaData[name]; !ok {\n\t\treturn \"\", errors.Errorf(\"config %s not found\", name)\n\t}\n\n\tconfig := s.ConfigsMetaData[name]\n\tif config.External {\n\t\treturn \"\", errors.Errorf(\"config %s is external\", name)\n\t}\n\n\tif config.File != \"\" {\n\t\treturn filepath.Base(config.File), nil\n\t} else if config.Content != \"\" {\n\t\t// loop through s.Configs to find the config with the same name\n\t\tfor _, cfg := range s.Configs {\n\t\t\tif cfg.Source == name {\n\t\t\t\tif cfg.Target == \"\" {\n\t\t\t\t\treturn filepath.Base(cfg.Source), nil\n\t\t\t\t} else {\n\t\t\t\t\treturn filepath.Base(cfg.Target), nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn \"\", errors.Errorf(\"config %s is empty\", name)\n\t}\n\n\treturn \"\", errors.Errorf(\"config %s not found\", name)\n}\n\n// GetKubernetesUpdateStrategy from compose update_config\n// 1. only apply to Deployment, but the check is not happened here\n// 2. only support `parallelism` and `order`\n// return nil if not support\nfunc (s *ServiceConfig) GetKubernetesUpdateStrategy() *v1.RollingUpdateDeployment {\n\tconfig := s.DeployUpdateConfig\n\tr := v1.RollingUpdateDeployment{}\n\tif config.Order == \"stop-first\" {\n\t\tif config.Parallelism != nil {\n\t\t\tv := intstr.FromInt(cast.ToInt(*config.Parallelism))\n\t\t\tr.MaxUnavailable = &v\n\t\t}\n\n\t\tv := intstr.FromInt(0)\n\t\tr.MaxSurge = &v\n\t\treturn &r\n\t}\n\n\tif config.Order == \"start-first\" {\n\t\tif config.Parallelism != nil {\n\t\t\tv := intstr.FromInt(cast.ToInt(*config.Parallelism))\n\t\t\tr.MaxSurge = &v\n\t\t}\n\t\tv := intstr.FromInt(0)\n\t\tr.MaxUnavailable = &v\n\t\treturn &r\n\t}\n\treturn nil\n}\n\n// GetOSUpdateStrategy ...\nfunc (s *ServiceConfig) GetOSUpdateStrategy() *deployapi.RollingDeploymentStrategyParams {\n\tconfig := s.DeployUpdateConfig\n\tr := deployapi.RollingDeploymentStrategyParams{}\n\n\tdelay := time.Second * 1\n\tif config.Delay != 0 {\n\t\tdelay = time.Duration(config.Delay)\n\t}\n\n\tinterval := cast.ToInt64(delay.Seconds())\n\n\tif config.Order == \"stop-first\" {\n\t\tif config.Parallelism != nil {\n\t\t\tv := intstr.FromInt(cast.ToInt(*config.Parallelism))\n\t\t\tr.MaxUnavailable = &v\n\t\t}\n\t\t*r.MaxSurge = intstr.FromInt(0)\n\t\tr.UpdatePeriodSeconds = &interval\n\t\treturn &r\n\t}\n\n\tif config.Order == \"start-first\" {\n\t\tif config.Parallelism != nil {\n\t\t\tv := intstr.FromInt(cast.ToInt(*config.Parallelism))\n\t\t\tr.MaxSurge = &v\n\t\t}\n\n\t\tv := intstr.FromInt(0)\n\t\tr.MaxUnavailable = &v\n\t\tr.UpdatePeriodSeconds = &interval\n\t\treturn &r\n\t}\n\n\tif cast.ToInt64(config.Delay) != 0 {\n\t\tr.UpdatePeriodSeconds = &interval\n\t\treturn &r\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/loader/compose/compose.go",
    "content": "/*\nCopyright 2017 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\nhttp://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*/\n\npackage compose\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/compose-spec/compose-go/v2/cli\"\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\t\"github.com/fatih/structs\"\n\t\"github.com/google/shlex\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cast\"\n\tbatchv1 \"k8s.io/api/batch/v1\"\n\tapi \"k8s.io/api/core/v1\"\n)\n\n// StdinData is data bytes read from stdin\nvar StdinData []byte\n\n// Compose is docker compose file loader, implements Loader interface\ntype Compose struct {\n}\n\n// checkUnsupportedKey checks if compose-go project contains\n// keys that are not supported by this loader.\n// list of all unsupported keys are stored in unsupportedKey variable\n// returns list of unsupported YAML keys from docker-compose\nfunc checkUnsupportedKey(composeProject *types.Project) []string {\n\t// list of all unsupported keys for this loader\n\t// this is map to make searching for keys easier\n\t// to make sure that unsupported key is not going to be reported twice\n\t// by keeping record if already saw this key in another service\n\tvar unsupportedKey = map[string]bool{\n\t\t\"CgroupParent\":  false,\n\t\t\"CPUSet\":        false,\n\t\t\"CPUShares\":     false,\n\t\t\"Devices\":       false,\n\t\t\"DependsOn\":     false,\n\t\t\"DNS\":           false,\n\t\t\"DNSSearch\":     false,\n\t\t\"EnvFile\":       false,\n\t\t\"ExternalLinks\": false,\n\t\t\"ExtraHosts\":    false,\n\t\t\"Ipc\":           false,\n\t\t\"Logging\":       false,\n\t\t\"MacAddress\":    false,\n\t\t\"MemSwapLimit\":  false,\n\t\t\"NetworkMode\":   false,\n\t\t\"SecurityOpt\":   false,\n\t\t\"ShmSize\":       false,\n\t\t\"StopSignal\":    false,\n\t\t\"VolumeDriver\":  false,\n\t\t\"Uts\":           false,\n\t\t\"ReadOnly\":      false,\n\t\t\"Ulimits\":       false,\n\t\t\"Net\":           false,\n\t\t\"Sysctls\":       false,\n\t\t//\"Networks\":    false, // We shall be spporting network now. There are special checks for Network in checkUnsupportedKey function\n\t\t\"Links\": false,\n\t}\n\n\tvar keysFound []string\n\n\t// Root level keys are not yet supported except Network\n\t// Check to see if the default network is available and length is only equal to one.\n\tif _, ok := composeProject.Networks[\"default\"]; ok && len(composeProject.Networks) == 1 {\n\t\tlog.Debug(\"Default network found\")\n\t}\n\n\t// Root level volumes are not yet supported\n\tif len(composeProject.Volumes) > 0 {\n\t\tkeysFound = append(keysFound, \"root level volumes\")\n\t}\n\n\tfor _, serviceConfig := range composeProject.AllServices() {\n\t\t// this reflection is used in check for empty arrays\n\t\tval := reflect.ValueOf(serviceConfig)\n\t\ts := structs.New(serviceConfig)\n\n\t\tfor _, f := range s.Fields() {\n\t\t\t// Check if given key is among unsupported keys, and skip it if we already saw this key\n\t\t\tif alreadySaw, ok := unsupportedKey[f.Name()]; ok && !alreadySaw {\n\t\t\t\tif f.IsExported() && !f.IsZero() {\n\t\t\t\t\t// IsZero returns false for empty array/slice ([])\n\t\t\t\t\t// this check if field is Slice, and then it checks its size\n\t\t\t\t\tif field := val.FieldByName(f.Name()); field.Kind() == reflect.Slice {\n\t\t\t\t\t\tif field.Len() == 0 {\n\t\t\t\t\t\t\t// array is empty it doesn't matter if it is in unsupportedKey or not\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//get yaml tag name instead of variable name\n\t\t\t\t\tyamlTagName := strings.Split(f.Tag(\"yaml\"), \",\")[0]\n\t\t\t\t\tif f.Name() == \"Networks\" {\n\t\t\t\t\t\t// networks always contains one default element, even it isn't declared in compose v2.\n\t\t\t\t\t\tif len(serviceConfig.Networks) == 1 && serviceConfig.NetworksByPriority()[0] == \"default\" {\n\t\t\t\t\t\t\t// this is empty Network definition, skip it\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif linksArray := val.FieldByName(f.Name()); f.Name() == \"Links\" && linksArray.Kind() == reflect.Slice {\n\t\t\t\t\t\t//Links has \"SERVICE:ALIAS\" style, we don't support SERVICE != ALIAS\n\t\t\t\t\t\tfindUnsupportedLinksFlag := false\n\t\t\t\t\t\tfor i := 0; i < linksArray.Len(); i++ {\n\t\t\t\t\t\t\tif tmpLink := linksArray.Index(i); tmpLink.Kind() == reflect.String {\n\t\t\t\t\t\t\t\ttmpLinkStr := tmpLink.String()\n\t\t\t\t\t\t\t\ttmpLinkStrSplit := strings.Split(tmpLinkStr, \":\")\n\t\t\t\t\t\t\t\tif len(tmpLinkStrSplit) == 2 && tmpLinkStrSplit[0] != tmpLinkStrSplit[1] {\n\t\t\t\t\t\t\t\t\tfindUnsupportedLinksFlag = true\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !findUnsupportedLinksFlag {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tkeysFound = append(keysFound, yamlTagName)\n\t\t\t\t\tunsupportedKey[f.Name()] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn keysFound\n}\n\n// LoadFile loads a compose file into KomposeObject\nfunc (c *Compose) LoadFile(files []string, profiles []string, noInterpolate bool) (kobject.KomposeObject, error) {\n\t// Gather the working directory\n\tworkingDir, err := transformer.GetComposeFileDir(files)\n\tif err != nil {\n\t\treturn kobject.KomposeObject{}, err\n\t}\n\n\tprojectOptions, err := cli.NewProjectOptions(\n\t\tfiles, cli.WithOsEnv,\n\t\tcli.WithWorkingDirectory(workingDir),\n\t\tcli.WithInterpolation(!noInterpolate),\n\t\tcli.WithProfiles(profiles),\n\t\tcli.WithEnvFiles([]string{}...),\n\t\tcli.WithDotEnv,\n\t)\n\tif err != nil {\n\t\treturn kobject.KomposeObject{}, errors.Wrap(err, \"Unable to create compose options\")\n\t}\n\n\tproject, err := cli.ProjectFromOptions(context.Background(), projectOptions)\n\tif err != nil {\n\t\treturn kobject.KomposeObject{}, errors.Wrap(err, \"Unable to load files\")\n\t}\n\n\t// Finding 0 services means two things:\n\t// 1. The compose project is empty\n\t// 2. The profile that is configured in the compose project is different than the one defined in Kompose convert options\n\t// In both cases we should provide the user with a warning indicating that we didn't find any service.\n\tif len(project.Services) == 0 {\n\t\tlog.Warning(\"No service selected. The profile specified in services of your compose yaml may not exist.\")\n\t}\n\n\tkomposeObject, err := dockerComposeToKomposeMapping(project)\n\tif err != nil {\n\t\treturn kobject.KomposeObject{}, err\n\t}\n\treturn komposeObject, nil\n}\n\nfunc loadPlacement(placement types.Placement) kobject.Placement {\n\tkomposePlacement := kobject.Placement{\n\t\tPositiveConstraints: make(map[string]string),\n\t\tNegativeConstraints: make(map[string]string),\n\t\tPreferences:         make([]string, 0, len(placement.Preferences)),\n\t}\n\n\t// Convert constraints\n\tequal, notEqual := \" == \", \" != \"\n\tfor _, j := range placement.Constraints {\n\t\toperator := equal\n\t\tif strings.Contains(j, notEqual) {\n\t\t\toperator = notEqual\n\t\t}\n\t\tp := strings.Split(j, operator)\n\t\tif len(p) < 2 {\n\t\t\tlog.Warnf(\"Failed to parse placement constraints %s, the correct format is 'label == xxx'\", j)\n\t\t\tcontinue\n\t\t}\n\n\t\tkey, err := convertDockerLabel(p[0])\n\t\tif err != nil {\n\t\t\tlog.Warn(\"Ignore placement constraints: \", err.Error())\n\t\t\tcontinue\n\t\t}\n\n\t\tif operator == equal {\n\t\t\tkomposePlacement.PositiveConstraints[key] = p[1]\n\t\t} else if operator == notEqual {\n\t\t\tkomposePlacement.NegativeConstraints[key] = p[1]\n\t\t}\n\t}\n\n\t// Convert preferences\n\tfor _, p := range placement.Preferences {\n\t\t// Spread is the only supported strategy currently\n\t\tlabel, err := convertDockerLabel(p.Spread)\n\t\tif err != nil {\n\t\t\tlog.Warn(\"Ignore placement preferences: \", err.Error())\n\t\t\tcontinue\n\t\t}\n\t\tkomposePlacement.Preferences = append(komposePlacement.Preferences, label)\n\t}\n\treturn komposePlacement\n}\n\n// Convert docker label to k8s label\nfunc convertDockerLabel(dockerLabel string) (string, error) {\n\tswitch dockerLabel {\n\tcase \"node.hostname\":\n\t\treturn \"kubernetes.io/hostname\", nil\n\tcase \"engine.labels.operatingsystem\":\n\t\treturn \"kubernetes.io/os\", nil\n\tdefault:\n\t\tif strings.HasPrefix(dockerLabel, \"node.labels.\") {\n\t\t\treturn strings.TrimPrefix(dockerLabel, \"node.labels.\"), nil\n\t\t}\n\t}\n\terrMsg := fmt.Sprint(dockerLabel, \" is not supported, only 'node.hostname', 'engine.labels.operatingsystem' and 'node.labels.xxx' (ex: node.labels.something == anything) is supported\")\n\treturn \"\", errors.New(errMsg)\n}\n\n// Convert the Compose volumes to []string (the old way)\n// TODO: Check to see if it's a \"bind\" or \"volume\". Ignore for now.\n// TODO: Refactor it similar to loadPorts\n// See: https://docs.docker.com/compose/compose-file/#long-syntax-3\nfunc loadVolumes(volumes []types.ServiceVolumeConfig) []string {\n\tvar volArray []string\n\tfor _, vol := range volumes {\n\t\t// There will *always* be Source when parsing\n\t\tv := vol.Source\n\n\t\tif vol.Target != \"\" {\n\t\t\tv = v + \":\" + vol.Target\n\t\t}\n\n\t\tif vol.ReadOnly {\n\t\t\tv = v + \":ro\"\n\t\t}\n\n\t\tvolArray = append(volArray, v)\n\t}\n\treturn volArray\n}\n\n// Convert Compose ports to kobject.Ports\n// expose ports will be treated as TCP ports\nfunc loadPorts(ports []types.ServicePortConfig, expose []string) []kobject.Ports {\n\tkomposePorts := []kobject.Ports{}\n\texist := map[string]bool{}\n\n\tfor _, port := range ports {\n\t\t// Convert to a kobject struct with ports\n\t\tkomposePorts = append(komposePorts, kobject.Ports{\n\t\t\tHostPort:      cast.ToInt32(port.Published),\n\t\t\tContainerPort: int32(port.Target),\n\t\t\tHostIP:        port.HostIP,\n\t\t\tProtocol:      strings.ToUpper(port.Protocol),\n\t\t})\n\t\texist[cast.ToString(port.Target)+port.Protocol] = true\n\t}\n\n\tfor _, port := range expose {\n\t\tportValue := port\n\t\tprotocol := string(api.ProtocolTCP)\n\t\tif strings.Contains(portValue, \"/\") {\n\t\t\tsplits := strings.Split(port, \"/\")\n\t\t\tportValue = splits[0]\n\t\t\tprotocol = splits[1]\n\t\t}\n\n\t\tif exist[portValue+protocol] {\n\t\t\tcontinue\n\t\t}\n\t\tkomposePorts = append(komposePorts, kobject.Ports{\n\t\t\tContainerPort: cast.ToInt32(portValue),\n\t\t\tHostIP:        \"\",\n\t\t\tProtocol:      strings.ToUpper(protocol),\n\t\t})\n\t}\n\n\treturn komposePorts\n}\n\n/*\n\tConvert the HealthCheckConfig as designed by Docker to\n\na Kubernetes-compatible format.\n*/\nfunc parseHealthCheckReadiness(labels types.Labels) (kobject.HealthCheck, error) {\n\tvar test []string\n\tvar httpPath string\n\tvar httpPort, tcpPort, timeout, interval, retries, startPeriod int32\n\tvar disable bool\n\n\tfor key, value := range labels {\n\t\tswitch key {\n\t\tcase HealthCheckReadinessDisable:\n\t\t\tdisable = cast.ToBool(value)\n\t\tcase HealthCheckReadinessTest:\n\t\t\tif len(value) > 0 {\n\t\t\t\ttest, _ = shlex.Split(value)\n\t\t\t}\n\t\tcase HealthCheckReadinessHTTPGetPath:\n\t\t\thttpPath = value\n\t\tcase HealthCheckReadinessHTTPGetPort:\n\t\t\thttpPort = cast.ToInt32(value)\n\t\tcase HealthCheckReadinessTCPPort:\n\t\t\ttcpPort = cast.ToInt32(value)\n\t\tcase HealthCheckReadinessInterval:\n\t\t\tparse, err := time.ParseDuration(value)\n\t\t\tif err != nil {\n\t\t\t\treturn kobject.HealthCheck{}, errors.Wrap(err, \"unable to parse health check interval variable\")\n\t\t\t}\n\t\t\tinterval = int32(parse.Seconds())\n\t\tcase HealthCheckReadinessTimeout:\n\t\t\tparse, err := time.ParseDuration(value)\n\t\t\tif err != nil {\n\t\t\t\treturn kobject.HealthCheck{}, errors.Wrap(err, \"unable to parse health check timeout variable\")\n\t\t\t}\n\t\t\ttimeout = int32(parse.Seconds())\n\t\tcase HealthCheckReadinessRetries:\n\t\t\tretries = cast.ToInt32(value)\n\t\tcase HealthCheckReadinessStartPeriod:\n\t\t\tparse, err := time.ParseDuration(value)\n\t\t\tif err != nil {\n\t\t\t\treturn kobject.HealthCheck{}, errors.Wrap(err, \"unable to parse health check startPeriod variable\")\n\t\t\t}\n\t\t\tstartPeriod = int32(parse.Seconds())\n\t\t}\n\t}\n\n\tif len(test) > 0 {\n\t\tif test[0] == \"NONE\" {\n\t\t\tdisable = true\n\t\t\ttest = test[1:]\n\t\t}\n\t\t// Due to docker/cli adding \"CMD-SHELL\" to the struct, we remove the first element of composeHealthCheck.Test\n\t\tif test[0] == \"CMD\" || test[0] == \"CMD-SHELL\" {\n\t\t\ttest = test[1:]\n\t\t}\n\t}\n\n\treturn kobject.HealthCheck{\n\t\tTest:        test,\n\t\tHTTPPath:    httpPath,\n\t\tHTTPPort:    httpPort,\n\t\tTCPPort:     tcpPort,\n\t\tTimeout:     timeout,\n\t\tInterval:    interval,\n\t\tRetries:     retries,\n\t\tStartPeriod: startPeriod,\n\t\tDisable:     disable,\n\t}, nil\n}\n\n/*\n\tConvert the HealthCheckConfig as designed by Docker to\n\na Kubernetes-compatible format.\n*/\nfunc parseHealthCheck(composeHealthCheck types.HealthCheckConfig, labels types.Labels) (kobject.HealthCheck, error) {\n\tvar httpPort, tcpPort, timeout, interval, retries, startPeriod int32\n\tvar test []string\n\tvar httpPath string\n\n\t// Here we convert the timeout from 1h30s (example) to 36030 seconds.\n\tif composeHealthCheck.Timeout != nil {\n\t\tparse, err := time.ParseDuration(composeHealthCheck.Timeout.String())\n\t\tif err != nil {\n\t\t\treturn kobject.HealthCheck{}, errors.Wrap(err, \"unable to parse health check timeout variable\")\n\t\t}\n\t\ttimeout = int32(parse.Seconds())\n\t}\n\n\tif composeHealthCheck.Interval != nil {\n\t\tparse, err := time.ParseDuration(composeHealthCheck.Interval.String())\n\t\tif err != nil {\n\t\t\treturn kobject.HealthCheck{}, errors.Wrap(err, \"unable to parse health check interval variable\")\n\t\t}\n\t\tinterval = int32(parse.Seconds())\n\t}\n\n\tif composeHealthCheck.Retries != nil {\n\t\tretries = int32(*composeHealthCheck.Retries)\n\t}\n\n\tif composeHealthCheck.StartPeriod != nil {\n\t\tparse, err := time.ParseDuration(composeHealthCheck.StartPeriod.String())\n\t\tif err != nil {\n\t\t\treturn kobject.HealthCheck{}, errors.Wrap(err, \"unable to parse health check startPeriod variable\")\n\t\t}\n\t\tstartPeriod = int32(parse.Seconds())\n\t}\n\n\tif composeHealthCheck.Test != nil {\n\t\ttest = composeHealthCheck.Test[1:]\n\t}\n\n\tfor key, value := range labels {\n\t\tswitch key {\n\t\tcase HealthCheckLivenessHTTPGetPath:\n\t\t\thttpPath = value\n\t\tcase HealthCheckLivenessHTTPGetPort:\n\t\t\thttpPort = cast.ToInt32(value)\n\t\tcase HealthCheckLivenessTCPPort:\n\t\t\ttcpPort = cast.ToInt32(value)\n\t\t}\n\t}\n\n\t// Due to docker/cli adding \"CMD-SHELL\" to the struct, we remove the first element of composeHealthCheck.Test\n\treturn kobject.HealthCheck{\n\t\tTest:        test,\n\t\tTCPPort:     tcpPort,\n\t\tHTTPPath:    httpPath,\n\t\tHTTPPort:    httpPort,\n\t\tTimeout:     timeout,\n\t\tInterval:    interval,\n\t\tRetries:     retries,\n\t\tStartPeriod: startPeriod,\n\t}, nil\n}\n\nfunc dockerComposeToKomposeMapping(composeObject *types.Project) (kobject.KomposeObject, error) {\n\t// Step 1. Initialize what's going to be returned\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: make(map[string]kobject.ServiceConfig),\n\t\tLoadedFrom:     \"compose\",\n\t\tSecrets:        composeObject.Secrets,\n\t}\n\n\t// Step 2. Parse through the object and convert it to kobject.KomposeObject!\n\t// Here we \"clean up\" the service configuration so we return something that includes\n\t// all relevant information as well as avoid the unsupported keys as well.\n\tfor _, composeServiceConfig := range composeObject.Services {\n\t\t// Standard import\n\t\t// No need to modify before importation\n\t\tname := parseResourceName(composeServiceConfig.Name, composeServiceConfig.Labels)\n\t\tserviceConfig := kobject.ServiceConfig{}\n\t\tserviceConfig.Name = name\n\t\tserviceConfig.Image = composeServiceConfig.Image\n\t\tserviceConfig.WorkingDir = composeServiceConfig.WorkingDir\n\t\tserviceConfig.Annotations = composeServiceConfig.Labels\n\t\tserviceConfig.CapAdd = composeServiceConfig.CapAdd\n\t\tserviceConfig.CapDrop = composeServiceConfig.CapDrop\n\t\tserviceConfig.Expose = composeServiceConfig.Expose\n\t\tserviceConfig.Privileged = composeServiceConfig.Privileged\n\t\tserviceConfig.User = composeServiceConfig.User\n\t\tserviceConfig.ReadOnly = composeServiceConfig.ReadOnly\n\t\tserviceConfig.Stdin = composeServiceConfig.StdinOpen\n\t\tserviceConfig.Tty = composeServiceConfig.Tty\n\t\tserviceConfig.TmpFs = composeServiceConfig.Tmpfs\n\t\tserviceConfig.ContainerName = normalizeContainerNames(composeServiceConfig.ContainerName)\n\t\tserviceConfig.Command = composeServiceConfig.Entrypoint\n\t\tserviceConfig.Args = composeServiceConfig.Command\n\t\tserviceConfig.Labels = composeServiceConfig.Labels\n\t\tserviceConfig.HostName = composeServiceConfig.Hostname\n\t\tserviceConfig.DomainName = composeServiceConfig.DomainName\n\t\tserviceConfig.Secrets = composeServiceConfig.Secrets\n\t\tserviceConfig.NetworkMode = composeServiceConfig.NetworkMode\n\n\t\tif composeServiceConfig.StopGracePeriod != nil {\n\t\t\tserviceConfig.StopGracePeriod = composeServiceConfig.StopGracePeriod.String()\n\t\t}\n\n\t\tif err := parseNetwork(&composeServiceConfig, &serviceConfig, composeObject); err != nil {\n\t\t\treturn kobject.KomposeObject{}, err\n\t\t}\n\n\t\tif err := parseResources(&composeServiceConfig, &serviceConfig); err != nil {\n\t\t\treturn kobject.KomposeObject{}, err\n\t\t}\n\n\t\tserviceConfig.Restart = composeServiceConfig.Restart\n\n\t\tif composeServiceConfig.Deploy != nil {\n\t\t\t// Deploy keys\n\t\t\t// mode:\n\t\t\tserviceConfig.DeployMode = composeServiceConfig.Deploy.Mode\n\t\t\t// labels\n\t\t\tserviceConfig.DeployLabels = composeServiceConfig.Deploy.Labels\n\n\t\t\t// restart-policy: deploy.restart_policy.condition will rewrite restart option\n\t\t\t// see: https://docs.docker.com/compose/compose-file/#restart_policy\n\t\t\tif composeServiceConfig.Deploy.RestartPolicy != nil {\n\t\t\t\tserviceConfig.Restart = composeServiceConfig.Deploy.RestartPolicy.Condition\n\t\t\t}\n\n\t\t\t// replicas:\n\t\t\tif composeServiceConfig.Deploy.Replicas != nil {\n\t\t\t\tserviceConfig.Replicas = int(*composeServiceConfig.Deploy.Replicas)\n\t\t\t}\n\n\t\t\t// placement:\n\t\t\tserviceConfig.Placement = loadPlacement(composeServiceConfig.Deploy.Placement)\n\n\t\t\tif composeServiceConfig.Deploy.UpdateConfig != nil {\n\t\t\t\tserviceConfig.DeployUpdateConfig = *composeServiceConfig.Deploy.UpdateConfig\n\t\t\t}\n\n\t\t\tif composeServiceConfig.Deploy.EndpointMode == \"vip\" {\n\t\t\t\tserviceConfig.ServiceType = string(api.ServiceTypeNodePort)\n\t\t\t}\n\t\t}\n\n\t\t// HealthCheck Liveness\n\t\tif composeServiceConfig.HealthCheck != nil && !composeServiceConfig.HealthCheck.Disable {\n\t\t\tvar err error\n\t\t\tserviceConfig.HealthChecks.Liveness, err = parseHealthCheck(*composeServiceConfig.HealthCheck, composeServiceConfig.Labels)\n\t\t\tif err != nil {\n\t\t\t\treturn kobject.KomposeObject{}, errors.Wrap(err, \"Unable to parse health check\")\n\t\t\t}\n\t\t}\n\n\t\t// HealthCheck Readiness\n\t\tvar readiness, errReadiness = parseHealthCheckReadiness(composeServiceConfig.Labels)\n\t\tif !readiness.Disable {\n\t\t\tserviceConfig.HealthChecks.Readiness = readiness\n\t\t\tif errReadiness != nil {\n\t\t\t\treturn kobject.KomposeObject{}, errors.Wrap(errReadiness, \"Unable to parse health check\")\n\t\t\t}\n\t\t}\n\n\t\tif serviceConfig.Restart == \"unless-stopped\" {\n\t\t\tlog.Warnf(\"Restart policy 'unless-stopped' in service %s is not supported, convert it to 'always'\", name)\n\t\t\tserviceConfig.Restart = \"always\"\n\t\t}\n\n\t\tif composeServiceConfig.Build != nil {\n\t\t\tserviceConfig.Build = composeServiceConfig.Build.Context\n\t\t\tserviceConfig.Dockerfile = composeServiceConfig.Build.Dockerfile\n\t\t\tserviceConfig.BuildArgs = composeServiceConfig.Build.Args\n\t\t\tserviceConfig.BuildLabels = composeServiceConfig.Build.Labels\n\t\t\tserviceConfig.BuildTarget = composeServiceConfig.Build.Target\n\t\t}\n\n\t\t// env\n\t\tparseEnvironment(&composeServiceConfig, &serviceConfig)\n\n\t\t// Get env_file\n\t\tparseEnvFiles(&composeServiceConfig, &serviceConfig)\n\n\t\t// Parse the ports\n\t\t// v3 uses a new format called \"long syntax\" starting in 3.2\n\t\t// https://docs.docker.com/compose/compose-file/#ports\n\n\t\t// here we will translate `expose` too, they basically means the same thing in kubernetes\n\t\tserviceConfig.Port = loadPorts(composeServiceConfig.Ports, serviceConfig.Expose)\n\n\t\t// Parse the volumes\n\t\t// Again, in v3, we use the \"long syntax\" for volumes in terms of parsing\n\t\t// https://docs.docker.com/compose/compose-file/#long-syntax-3\n\t\tserviceConfig.VolList = loadVolumes(composeServiceConfig.Volumes)\n\t\tif err := parseKomposeLabels(composeServiceConfig.Labels, &serviceConfig); err != nil {\n\t\t\treturn kobject.KomposeObject{}, err\n\t\t}\n\n\t\t// Log if the name will been changed\n\t\tif normalizeServiceNames(name) != name {\n\t\t\tlog.Infof(\"Service name in docker-compose has been changed from %q to %q\", name, normalizeServiceNames(name))\n\t\t}\n\n\t\tserviceConfig.Configs = composeServiceConfig.Configs\n\t\tserviceConfig.ConfigsMetaData = composeObject.Configs\n\n\t\t// Get GroupAdd, group should be mentioned in gid format but not the group name\n\t\tgroupAdd, err := getGroupAdd(composeServiceConfig.GroupAdd)\n\t\tif err != nil {\n\t\t\treturn kobject.KomposeObject{}, errors.Wrap(err, \"GroupAdd should be mentioned in gid format, not a group name\")\n\t\t}\n\t\tserviceConfig.GroupAdd = groupAdd\n\n\t\t// Final step, add to the array!\n\t\tkomposeObject.ServiceConfigs[normalizeServiceNames(name)] = serviceConfig\n\t}\n\n\thandleVolume(&komposeObject, &composeObject.Volumes)\n\treturn komposeObject, nil\n}\n\nfunc parseNetwork(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig, composeObject *types.Project) error {\n\tif len(composeServiceConfig.Networks) == 0 {\n\t\tif defaultNetwork, ok := composeObject.Networks[\"default\"]; ok {\n\t\t\tnormalizedNetworkName, err := normalizeNetworkNames(defaultNetwork.Name)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Unable to normalize network name\")\n\t\t\t}\n\t\t\tserviceConfig.Network = append(serviceConfig.Network, normalizedNetworkName)\n\t\t}\n\t} else {\n\t\tvar alias = \"\"\n\t\tfor key := range composeServiceConfig.Networks {\n\t\t\talias = key\n\t\t\tnetName := composeObject.Networks[alias].Name\n\n\t\t\t// if Network Name Field is empty in the docker-compose definition\n\t\t\t// we will use the alias name defined in service config file\n\t\t\tif netName == \"\" {\n\t\t\t\tnetName = alias\n\t\t\t}\n\n\t\t\tnormalizedNetworkName, err := normalizeNetworkNames(netName)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"Unable to normalize network name\")\n\t\t\t}\n\n\t\t\tserviceConfig.Network = append(serviceConfig.Network, normalizedNetworkName)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc parseResources(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) error {\n\tserviceConfig.MemLimit = composeServiceConfig.MemLimit\n\n\tif composeServiceConfig.Deploy != nil {\n\t\t// memory:\n\t\t// See: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/\n\t\t// \"The expression 0.1 is equivalent to the expression 100m, which can be read as “one hundred millicpu”.\"\n\n\t\t// Since Deploy.Resources.Limits does not initialize, we must check type Resources before continuing\n\t\tif composeServiceConfig.Deploy.Resources.Limits != nil {\n\t\t\tserviceConfig.MemLimit = composeServiceConfig.Deploy.Resources.Limits.MemoryBytes\n\n\t\t\tif composeServiceConfig.Deploy.Resources.Limits.NanoCPUs > 0 {\n\t\t\t\tserviceConfig.CPULimit = int64(composeServiceConfig.Deploy.Resources.Limits.NanoCPUs * 1000)\n\t\t\t}\n\t\t}\n\t\tif composeServiceConfig.Deploy.Resources.Reservations != nil {\n\t\t\tserviceConfig.MemReservation = composeServiceConfig.Deploy.Resources.Reservations.MemoryBytes\n\n\t\t\tif composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs > 0 {\n\t\t\t\tserviceConfig.CPUReservation = int64(composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs * 1000)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc parseEnvironment(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) {\n\t// Gather the environment values\n\t// DockerCompose uses map[string]*string while we use []string\n\t// So let's convert that using this hack\n\t// Note: unset env pick up the env value on host if exist\n\tfor name, value := range composeServiceConfig.Environment {\n\t\tvar env kobject.EnvVar\n\t\tif value != nil {\n\t\t\tenv = kobject.EnvVar{Name: name, Value: *value}\n\t\t} else {\n\t\t\tresult, ok := os.LookupEnv(name)\n\t\t\tif ok {\n\t\t\t\tenv = kobject.EnvVar{Name: name, Value: result}\n\t\t\t} else {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tserviceConfig.Environment = append(serviceConfig.Environment, env)\n\t}\n}\n\nfunc parseEnvFiles(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) {\n\tfor _, value := range composeServiceConfig.EnvFiles {\n\t\tserviceConfig.EnvFile = append(serviceConfig.EnvFile, value.Path)\n\t\t// value.Required is ignored\n\t}\n}\n\nfunc handleCronJobConcurrencyPolicy(policy string) (batchv1.ConcurrencyPolicy, error) {\n\tswitch policy {\n\tcase \"Allow\":\n\t\treturn batchv1.AllowConcurrent, nil\n\tcase \"Forbid\":\n\t\treturn batchv1.ForbidConcurrent, nil\n\tcase \"Replace\":\n\t\treturn batchv1.ReplaceConcurrent, nil\n\tcase \"\":\n\t\treturn \"\", nil\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"invalid cronjob concurrency policy: %s\", policy)\n\t}\n}\n\nfunc handleCronJobBackoffLimit(backoffLimit string) (*int32, error) {\n\tif backoffLimit == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tlimit, err := cast.ToInt32E(backoffLimit)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid cronjob backoff limit: %s\", backoffLimit)\n\t}\n\treturn &limit, nil\n}\n\nfunc handleCronJobSchedule(schedule string) (string, error) {\n\tif schedule == \"\" {\n\t\treturn \"\", fmt.Errorf(\"cronjob schedule cannot be empty\")\n\t}\n\n\treturn schedule, nil\n\n}\n\n// parseKomposeLabels parse kompose labels, also do some validation\nfunc parseKomposeLabels(labels map[string]string, serviceConfig *kobject.ServiceConfig) error {\n\t// Label handler\n\t// Labels used to influence conversion of kompose will be handled\n\t// from here for docker-compose. Each loader will have such handler.\n\tif serviceConfig.Labels == nil {\n\t\tserviceConfig.Labels = make(map[string]string)\n\t}\n\n\tfor key, value := range labels {\n\t\tswitch key {\n\t\tcase LabelServiceType:\n\t\t\tserviceType, err := handleServiceType(value)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"handleServiceType failed\")\n\t\t\t}\n\n\t\t\tserviceConfig.ServiceType = serviceType\n\t\tcase LabelServiceExternalTrafficPolicy:\n\t\t\tserviceExternalTypeTrafficPolicy, err := handleServiceExternalTrafficPolicy(value)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"handleServiceExternalTrafficPolicy failed\")\n\t\t\t}\n\n\t\t\tserviceConfig.ServiceExternalTrafficPolicy = serviceExternalTypeTrafficPolicy\n\t\tcase LabelSecurityContextFsGroup:\n\t\t\tserviceConfig.FsGroup = cast.ToInt64(value)\n\t\tcase LabelExposeContainerToHost:\n\t\t\tserviceConfig.ExposeContainerToHost = cast.ToBool(value)\n\t\tcase LabelServiceExpose:\n\t\t\tserviceConfig.ExposeService = strings.Trim(value, \" ,\")\n\t\tcase LabelNodePortPort:\n\t\t\tserviceConfig.NodePortPort = cast.ToInt32(value)\n\t\tcase LabelServiceExposeTLSSecret:\n\t\t\tserviceConfig.ExposeServiceTLS = value\n\t\tcase LabelServiceExposeIngressClassName:\n\t\t\tserviceConfig.ExposeServiceIngressClassName = value\n\t\tcase LabelImagePullSecret:\n\t\t\tserviceConfig.ImagePullSecret = value\n\t\tcase LabelImagePullPolicy:\n\t\t\tserviceConfig.ImagePullPolicy = value\n\t\tcase LabelContainerVolumeSubpath:\n\t\t\tserviceConfig.VolumeMountSubPath = value\n\t\tcase LabelCronJobSchedule:\n\t\t\tcronJobSchedule, err := handleCronJobSchedule(value)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"handleCronJobSchedule failed\")\n\t\t\t}\n\n\t\t\tserviceConfig.CronJobSchedule = cronJobSchedule\n\t\tcase LabelCronJobConcurrencyPolicy:\n\t\t\tcronJobConcurrencyPolicy, err := handleCronJobConcurrencyPolicy(value)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"handleCronJobConcurrencyPolicy failed\")\n\t\t\t}\n\n\t\t\tserviceConfig.CronJobConcurrencyPolicy = cronJobConcurrencyPolicy\n\t\tcase LabelCronJobBackoffLimit:\n\t\t\tcronJobBackoffLimit, err := handleCronJobBackoffLimit(value)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"handleCronJobBackoffLimit failed\")\n\t\t\t}\n\n\t\t\tserviceConfig.CronJobBackoffLimit = cronJobBackoffLimit\n\t\tcase LabelNameOverride:\n\t\t\t// generate a valid k8s resource name\n\t\t\tnormalizedName := normalizeServiceNames(value)\n\t\t\tserviceConfig.Name = normalizedName\n\t\tdefault:\n\t\t\tserviceConfig.Labels[key] = value\n\t\t}\n\t}\n\n\tif serviceConfig.ExposeService == \"\" && serviceConfig.ExposeServiceTLS != \"\" {\n\t\treturn errors.New(\"kompose.service.expose.tls-secret was specified without kompose.service.expose\")\n\t}\n\n\tif serviceConfig.ExposeService == \"\" && serviceConfig.ExposeServiceIngressClassName != \"\" {\n\t\treturn errors.New(\"kompose.service.expose.ingress-class-name was specified without kompose.service.expose\")\n\t}\n\n\tif serviceConfig.ServiceType != string(api.ServiceTypeNodePort) && serviceConfig.NodePortPort != 0 {\n\t\treturn errors.New(\"kompose.service.type must be nodeport when assign node port value\")\n\t}\n\n\tif len(serviceConfig.Port) > 1 && serviceConfig.NodePortPort != 0 {\n\t\treturn errors.New(\"cannot set kompose.service.nodeport.port when service has multiple ports\")\n\t}\n\n\tif serviceConfig.Restart == \"always\" && serviceConfig.CronJobConcurrencyPolicy != \"\" {\n\t\tlog.Infof(\"cronjob restart policy will be converted from '%s' to 'on-failure'\", serviceConfig.Restart)\n\t\tserviceConfig.Restart = \"on-failure\"\n\t}\n\n\treturn nil\n}\n\nfunc handleVolume(komposeObject *kobject.KomposeObject, volumes *types.Volumes) {\n\tfor name := range komposeObject.ServiceConfigs {\n\t\t// retrieve volumes of service\n\t\tvols, err := retrieveVolume(name, *komposeObject)\n\t\tif err != nil {\n\t\t\terrors.Wrap(err, \"could not retrieve vvolume\")\n\t\t}\n\t\tfor volName, vol := range vols {\n\t\t\tsize, selector := getVolumeLabels(vol.VolumeName, volumes)\n\t\t\tif len(size) > 0 || len(selector) > 0 {\n\t\t\t\t// We can't assign value to struct field in map while iterating over it, so temporary variable `temp` is used here\n\t\t\t\tvar temp = vols[volName]\n\t\t\t\ttemp.PVCSize = size\n\t\t\t\ttemp.SelectorValue = selector\n\t\t\t\tvols[volName] = temp\n\t\t\t}\n\t\t}\n\t\t// We can't assign value to struct field in map while iterating over it, so temporary variable `temp` is used here\n\t\tvar temp = komposeObject.ServiceConfigs[name]\n\t\ttemp.Volumes = vols\n\t\tkomposeObject.ServiceConfigs[name] = temp\n\t}\n}\n\n// returns all volumes associated with service, if `volumes_from` key is used, we have to retrieve volumes from the services which are mentioned there. Hence, recursive function is used here.\nfunc retrieveVolume(svcName string, komposeObject kobject.KomposeObject) (volume []kobject.Volumes, err error) {\n\t// if volumes-from key is present\n\tif komposeObject.ServiceConfigs[svcName].VolumesFrom != nil {\n\t\t// iterating over services from `volumes-from`\n\t\tfor _, depSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {\n\t\t\t// recursive call for retrieving volumes of services from `volumes-from`\n\t\t\tdVols, err := retrieveVolume(depSvc, komposeObject)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrapf(err, \"could not retrieve the volume\")\n\t\t\t}\n\t\t\tvar cVols []kobject.Volumes\n\t\t\tcVols, err = ParseVols(komposeObject.ServiceConfigs[svcName].VolList, svcName)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrapf(err, \"error generating current volumes\")\n\t\t\t}\n\n\t\t\tfor _, cv := range cVols {\n\t\t\t\t// check whether volumes of current service is same or not as that of dependent volumes coming from `volumes-from`\n\t\t\t\tok, dv := getVol(cv, dVols)\n\t\t\t\tif ok {\n\t\t\t\t\t// change current volumes service name to dependent service name\n\t\t\t\t\tif dv.VFrom == \"\" {\n\t\t\t\t\t\tcv.VFrom = dv.SvcName\n\t\t\t\t\t\tcv.SvcName = dv.SvcName\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcv.VFrom = dv.VFrom\n\t\t\t\t\t\tcv.SvcName = dv.SvcName\n\t\t\t\t\t}\n\t\t\t\t\tcv.PVCName = dv.PVCName\n\t\t\t\t}\n\t\t\t\tvolume = append(volume, cv)\n\t\t\t}\n\t\t\t// iterating over dependent volumes\n\t\t\tfor _, dv := range dVols {\n\t\t\t\t// check whether dependent volume is already present or not\n\t\t\t\tif checkVolDependent(dv, volume) {\n\t\t\t\t\t// if found, add service name to `VFrom`\n\t\t\t\t\tdv.VFrom = dv.SvcName\n\t\t\t\t\tvolume = append(volume, dv)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// if `volumes-from` is not present\n\t\tvolume, err = ParseVols(komposeObject.ServiceConfigs[svcName].VolList, svcName)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"error generating current volumes\")\n\t\t}\n\t}\n\treturn\n}\n\n// checkVolDependent returns false if dependent volume is present\nfunc checkVolDependent(dv kobject.Volumes, volume []kobject.Volumes) bool {\n\tfor _, vol := range volume {\n\t\tif vol.PVCName == dv.PVCName {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// ParseVols parse volumes\nfunc ParseVols(volNames []string, svcName string) ([]kobject.Volumes, error) {\n\tvar volumes []kobject.Volumes\n\tvar err error\n\n\tfor i, vn := range volNames {\n\t\tvar v kobject.Volumes\n\t\tv.VolumeName, v.Host, v.Container, v.Mode, err = transformer.ParseVolume(vn)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"could not parse volume %q: %v\", vn, err)\n\t\t}\n\t\tv.VolumeName = normalizeVolumes(v.VolumeName)\n\t\tv.SvcName = svcName\n\t\tv.MountPath = fmt.Sprintf(\"%s:%s\", v.Host, v.Container)\n\t\tv.PVCName = fmt.Sprintf(\"%s-claim%d\", v.SvcName, i)\n\t\tvolumes = append(volumes, v)\n\t}\n\n\treturn volumes, nil\n}\n\n// for dependent volumes, returns true and the respective volume if mountpath are same\nfunc getVol(toFind kobject.Volumes, Vols []kobject.Volumes) (bool, kobject.Volumes) {\n\tfor _, dv := range Vols {\n\t\tif toFind.MountPath == dv.MountPath {\n\t\t\treturn true, dv\n\t\t}\n\t}\n\treturn false, kobject.Volumes{}\n}\n\nfunc getVolumeLabels(name string, volumes *types.Volumes) (string, string) {\n\tsize, selector := \"\", \"\"\n\n\tif volume, ok := (*volumes)[name]; ok {\n\t\tfor key, value := range volume.Labels {\n\t\t\tif key == \"kompose.volume.size\" {\n\t\t\t\tsize = value\n\t\t\t} else if key == \"kompose.volume.selector\" {\n\t\t\t\tselector = value\n\t\t\t}\n\t\t}\n\t}\n\n\treturn size, selector\n}\n\n// getGroupAdd will return group in int64 format\nfunc getGroupAdd(group []string) ([]int64, error) {\n\tvar groupAdd []int64\n\tfor _, i := range group {\n\t\tj, err := strconv.Atoi(i)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"unable to get group_add key\")\n\t\t}\n\t\tgroupAdd = append(groupAdd, int64(j))\n\t}\n\treturn groupAdd, nil\n}\n"
  },
  {
    "path": "pkg/loader/compose/compose_test.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage compose\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/pkg/errors\"\n\tapi \"k8s.io/api/core/v1\"\n)\n\nfunc durationTypesPtr(value time.Duration) *types.Duration {\n\ttarget := types.Duration(value)\n\treturn &target\n}\n\nfunc TestParseHealthCheck(t *testing.T) {\n\thelperValue := uint64(2)\n\ttype input struct {\n\t\thealthCheck types.HealthCheckConfig\n\t\tlabels      types.Labels\n\t}\n\ttestCases := map[string]struct {\n\t\tinput    input\n\t\texpected kobject.HealthCheck\n\t}{\n\t\t\"Exec\": {\n\t\t\tinput: input{\n\t\t\t\thealthCheck: types.HealthCheckConfig{\n\t\t\t\t\tTest:        []string{\"CMD-SHELL\", \"echo\", \"foobar\"},\n\t\t\t\t\tTimeout:     durationTypesPtr(1 * time.Second),\n\t\t\t\t\tInterval:    durationTypesPtr(2 * time.Second),\n\t\t\t\t\tRetries:     &helperValue,\n\t\t\t\t\tStartPeriod: durationTypesPtr(3 * time.Second),\n\t\t\t\t},\n\t\t\t},\n\t\t\t// CMD-SHELL or SHELL is included Test within docker/cli, thus we remove the first value in Test\n\t\t\texpected: kobject.HealthCheck{\n\t\t\t\tTest:        []string{\"echo\", \"foobar\"},\n\t\t\t\tTimeout:     1,\n\t\t\t\tInterval:    2,\n\t\t\t\tRetries:     2,\n\t\t\t\tStartPeriod: 3,\n\t\t\t},\n\t\t},\n\t\t\"HTTPGet\": {\n\t\t\tinput: input{\n\t\t\t\thealthCheck: types.HealthCheckConfig{\n\t\t\t\t\tTimeout:     durationTypesPtr(1 * time.Second),\n\t\t\t\t\tInterval:    durationTypesPtr(2 * time.Second),\n\t\t\t\t\tRetries:     &helperValue,\n\t\t\t\t\tStartPeriod: durationTypesPtr(3 * time.Second),\n\t\t\t\t},\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\t\"kompose.service.healthcheck.liveness.http_get_path\": \"/health\",\n\t\t\t\t\t\"kompose.service.healthcheck.liveness.http_get_port\": \"8080\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpected: kobject.HealthCheck{\n\t\t\t\tHTTPPath:    \"/health\",\n\t\t\t\tHTTPPort:    8080,\n\t\t\t\tTimeout:     1,\n\t\t\t\tInterval:    2,\n\t\t\t\tRetries:     2,\n\t\t\t\tStartPeriod: 3,\n\t\t\t},\n\t\t},\n\t\t\"TCPSocket\": {\n\t\t\tinput: input{\n\t\t\t\thealthCheck: types.HealthCheckConfig{\n\t\t\t\t\tTimeout:     durationTypesPtr(1 * time.Second),\n\t\t\t\t\tInterval:    durationTypesPtr(2 * time.Second),\n\t\t\t\t\tRetries:     &helperValue,\n\t\t\t\t\tStartPeriod: durationTypesPtr(3 * time.Second),\n\t\t\t\t},\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\t\"kompose.service.healthcheck.liveness.tcp_port\": \"8080\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpected: kobject.HealthCheck{\n\t\t\t\tTCPPort:     8080,\n\t\t\t\tTimeout:     1,\n\t\t\t\tInterval:    2,\n\t\t\t\tRetries:     2,\n\t\t\t\tStartPeriod: 3,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor name, testCase := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\toutput, err := parseHealthCheck(testCase.input.healthCheck, testCase.input.labels)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Unable to convert HealthCheckConfig: %s\", err)\n\t\t}\n\n\t\tif !reflect.DeepEqual(output, testCase.expected) {\n\t\t\tt.Errorf(\"Structs are not equal, expected: %v, output: %v\", testCase.expected, output)\n\t\t}\n\t}\n}\n\nfunc TestParseHealthCheckReadiness(t *testing.T) {\n\ttestCases := map[string]struct {\n\t\tinput    types.Labels\n\t\texpected kobject.HealthCheck\n\t}{\n\t\t\"Exec\": {\n\t\t\tinput: types.Labels{\n\t\t\t\t\"kompose.service.healthcheck.readiness.test\":         \"echo foobar\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.timeout\":      \"1s\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.interval\":     \"2s\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.retries\":      \"2\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.start_period\": \"3s\",\n\t\t\t},\n\t\t\texpected: kobject.HealthCheck{\n\t\t\t\tTest:        []string{\"echo\", \"foobar\"},\n\t\t\t\tTimeout:     1,\n\t\t\t\tInterval:    2,\n\t\t\t\tRetries:     2,\n\t\t\t\tStartPeriod: 3,\n\t\t\t},\n\t\t},\n\t\t\"HTTPGet\": {\n\t\t\tinput: types.Labels{\n\t\t\t\t\"kompose.service.healthcheck.readiness.http_get_path\": \"/ready\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.http_get_port\": \"8080\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.timeout\":       \"1s\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.interval\":      \"2s\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.retries\":       \"2\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.start_period\":  \"3s\",\n\t\t\t},\n\t\t\texpected: kobject.HealthCheck{\n\t\t\t\tHTTPPath:    \"/ready\",\n\t\t\t\tHTTPPort:    8080,\n\t\t\t\tTimeout:     1,\n\t\t\t\tInterval:    2,\n\t\t\t\tRetries:     2,\n\t\t\t\tStartPeriod: 3,\n\t\t\t},\n\t\t},\n\t\t\"TCPSocket\": {\n\t\t\tinput: types.Labels{\n\t\t\t\t\"kompose.service.healthcheck.readiness.tcp_port\":     \"8080\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.timeout\":      \"1s\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.interval\":     \"2s\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.retries\":      \"2\",\n\t\t\t\t\"kompose.service.healthcheck.readiness.start_period\": \"3s\",\n\t\t\t},\n\t\t\texpected: kobject.HealthCheck{\n\t\t\t\tTCPPort:     8080,\n\t\t\t\tTimeout:     1,\n\t\t\t\tInterval:    2,\n\t\t\t\tRetries:     2,\n\t\t\t\tStartPeriod: 3,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor name, testCase := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\toutput, err := parseHealthCheckReadiness(testCase.input)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Unable to convert HealthCheckConfig: %s\", err)\n\t\t}\n\n\t\tif !reflect.DeepEqual(output, testCase.expected) {\n\t\t\tt.Errorf(\"Structs are not equal, expected: %v, output: %v\", testCase.expected, output)\n\t\t}\n\t}\n}\n\nfunc TestLoadV3Volumes(t *testing.T) {\n\tvol := types.ServiceVolumeConfig{\n\t\tType:     \"volume\",\n\t\tSource:   \"/tmp/foobar\",\n\t\tTarget:   \"/tmp/foobar\",\n\t\tReadOnly: true,\n\t}\n\tvolumes := []types.ServiceVolumeConfig{vol}\n\toutput := loadVolumes(volumes)\n\texpected := \"/tmp/foobar:/tmp/foobar:ro\"\n\n\tif output[0] != expected {\n\t\tt.Errorf(\"Expected %s, got %s\", expected, output[0])\n\t}\n}\n\nfunc TestLoadV3Ports(t *testing.T) {\n\tfor _, tt := range []struct {\n\t\tdesc   string\n\t\tports  []types.ServicePortConfig\n\t\texpose []string\n\t\twant   []kobject.Ports\n\t}{\n\t\t{\n\t\t\tdesc:   \"ports with expose\",\n\t\t\tports:  []types.ServicePortConfig{{Target: 80, Published: \"80\", Protocol: string(api.ProtocolTCP)}},\n\t\t\texpose: []string{\"80\", \"8080\"},\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 8080, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:   \"exposed port including /protocol\",\n\t\t\tports:  []types.ServicePortConfig{{Target: 80, Published: \"80\", Protocol: string(api.ProtocolTCP)}},\n\t\t\texpose: []string{\"80/udp\"},\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 80, Protocol: string(api.ProtocolUDP)},\n\t\t\t},\n\t\t},\n\t} {\n\t\tt.Run(tt.desc, func(t *testing.T) {\n\t\t\tgot := loadPorts(tt.ports, tt.expose)\n\t\t\tif diff := cmp.Diff(tt.want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"loadV3Ports() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test if service types are parsed properly on user input\n// give a service type and expect correct input\nfunc TestHandleServiceType(t *testing.T) {\n\ttests := []struct {\n\t\tlabelValue  string\n\t\tserviceType string\n\t}{\n\t\t{\"NodePort\", \"NodePort\"},\n\t\t{\"nodeport\", \"NodePort\"},\n\t\t{\"LoadBalancer\", \"LoadBalancer\"},\n\t\t{\"loadbalancer\", \"LoadBalancer\"},\n\t\t{\"ClusterIP\", \"ClusterIP\"},\n\t\t{\"clusterip\", \"ClusterIP\"},\n\t\t{\"\", \"ClusterIP\"},\n\t}\n\n\tfor _, tt := range tests {\n\t\tresult, err := handleServiceType(tt.labelValue)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"handleServiceType failed\"))\n\t\t}\n\t\tif result != tt.serviceType {\n\t\t\tt.Errorf(\"Expected %q, got %q\", tt.serviceType, result)\n\t\t}\n\t}\n}\n\n// Test loading of ports\nfunc TestLoadPorts(t *testing.T) {\n\tportWithIPAddress, _ := types.ParsePortConfig(\"127.0.0.1:80:80/tcp\")\n\tportWithoutIPAddress, _ := types.ParsePortConfig(\"80:80/tcp\")\n\tportWithoutProtocol, _ := types.ParsePortConfig(\"80:80\")\n\tsinglePort, _ := types.ParsePortConfig(\"80\")\n\tsinglePortsRange, _ := types.ParsePortConfig(\"3000-3002\")\n\ttargetAndContainerPortsRange, _ := types.ParsePortConfig(\"3000-3002:5000-5002\")\n\ttargetAndContainerPortsRangeWithIPAddress, _ := types.ParsePortConfig(\"127.0.0.1:3000-3002:5000-5002\")\n\tport3000, _ := types.ParsePortConfig(\"3000\")\n\n\ttests := []struct {\n\t\tports  []types.ServicePortConfig\n\t\texpose []string\n\t\twant   []kobject.Ports\n\t}{\n\t\t{\n\t\t\tports: portWithIPAddress,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostIP: \"127.0.0.1\", HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: portWithoutIPAddress,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: portWithoutProtocol,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: singlePort,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: singlePortsRange,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 3001, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 3002, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: targetAndContainerPortsRange,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostPort: 3000, ContainerPort: 5000, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{HostPort: 3001, ContainerPort: 5001, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{HostPort: 3002, ContainerPort: 5002, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: targetAndContainerPortsRangeWithIPAddress,\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostIP: \"127.0.0.1\", HostPort: 3000, ContainerPort: 5000, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{HostIP: \"127.0.0.1\", HostPort: 3001, ContainerPort: 5001, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{HostIP: \"127.0.0.1\", HostPort: 3002, ContainerPort: 5002, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports: append(append([]types.ServicePortConfig{}, singlePort...), port3000...),\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{HostPort: 0, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{HostPort: 0, ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tports:  append(append([]types.ServicePortConfig{}, singlePort...), port3000...),\n\t\t\texpose: []string{\"80\", \"8080\"},\n\t\t\twant: []kobject.Ports{\n\t\t\t\t{ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 80, Protocol: string(api.ProtocolTCP)},\n\t\t\t\t{ContainerPort: 8080, Protocol: string(api.ProtocolTCP)},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(fmt.Sprintf(\"port=%q,expose=%q\", tt.ports, tt.expose), func(t *testing.T) {\n\t\t\tgot := loadPorts(tt.ports, tt.expose)\n\t\t\tif diff := cmp.Diff(tt.want, got); diff != \"\" {\n\t\t\t\tt.Errorf(\"loadPorts() mismatch (-want +got):\\n%s\", diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestLoadEnvVar(t *testing.T) {\n\tev1 := []string{\"foo=bar\"}\n\trs1 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"bar\",\n\t}\n\tev2 := []string{\"foo:bar\"}\n\trs2 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"bar\",\n\t}\n\tev3 := []string{\"foo\"}\n\trs3 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"\",\n\t}\n\tev4 := []string{\"osfoo\"}\n\trs4 := kobject.EnvVar{\n\t\tName:  \"osfoo\",\n\t\tValue: \"osbar\",\n\t}\n\tev5 := []string{\"foo:bar=foobar\"}\n\trs5 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"bar=foobar\",\n\t}\n\tev6 := []string{\"foo=foo:bar\"}\n\trs6 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"foo:bar\",\n\t}\n\tev7 := []string{\"foo:\"}\n\trs7 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"\",\n\t}\n\tev8 := []string{\"foo=\"}\n\trs8 := kobject.EnvVar{\n\t\tName:  \"foo\",\n\t\tValue: \"\",\n\t}\n\n\ttests := []struct {\n\t\tenvvars []string\n\t\tresults kobject.EnvVar\n\t}{\n\t\t{ev1, rs1},\n\t\t{ev2, rs2},\n\t\t{ev3, rs3},\n\t\t{ev4, rs4},\n\t\t{ev5, rs5},\n\t\t{ev6, rs6},\n\t\t{ev7, rs7},\n\t\t{ev8, rs8},\n\t}\n\n\tos.Setenv(\"osfoo\", \"osbar\")\n\n\tfor _, tt := range tests {\n\t\tresult := loadEnvVars(tt.envvars)\n\t\tif result[0] != tt.results {\n\t\t\tt.Errorf(\"Expected %q, got %q\", tt.results, result[0])\n\t\t}\n\t}\n}\n\nfunc TestParseEnvFiles(t *testing.T) {\n\ttests := []struct {\n\t\tservice types.ServiceConfig\n\t\twant    []string\n\t}{\n\t\t{service: types.ServiceConfig{\n\t\t\tName:  \"baz\",\n\t\t\tImage: \"foo/baz\",\n\t\t\tEnvFiles: []types.EnvFile{\n\t\t\t\t{\n\t\t\t\t\tPath:     \"\",\n\t\t\t\t\tRequired: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:     \"foo\",\n\t\t\t\t\tRequired: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tPath:     \"bar\",\n\t\t\t\t\tRequired: true,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\twant: []string{\"\", \"foo\", \"bar\"},\n\t\t},\n\t\t{\n\t\t\tservice: types.ServiceConfig{\n\t\t\t\tName:     \"baz\",\n\t\t\t\tImage:    \"foo/baz\",\n\t\t\t\tEnvFiles: []types.EnvFile{},\n\t\t\t},\n\t\t\twant: []string{},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tsc := kobject.ServiceConfig{\n\t\t\tEnvFile: []string{},\n\t\t}\n\t\tparseEnvFiles(&tt.service, &sc)\n\t\tif !reflect.DeepEqual(sc.EnvFile, tt.want) {\n\t\t\tt.Errorf(\"Expected %q, got %q\", tt.want, sc.EnvFile)\n\t\t}\n\t}\n}\n\n// TestUnsupportedKeys test checkUnsupportedKey function with various\n// docker-compose projects\nfunc TestUnsupportedKeys(t *testing.T) {\n\t// create project that will be used in test cases\n\tprojectWithNetworks := &types.Project{\n\t\tNetworks: types.Networks{\n\t\t\t\"foo\": types.NetworkConfig{\n\t\t\t\tName:   \"foo\",\n\t\t\t\tDriver: \"bridge\",\n\t\t\t},\n\t\t},\n\t\tServices: types.Services{\n\t\t\t\"foo\": types.ServiceConfig{\n\t\t\t\tName:  \"foo\",\n\t\t\t\tImage: \"foo/bar\",\n\t\t\t\tBuild: &types.BuildConfig{\n\t\t\t\t\tContext: \"./build\",\n\t\t\t\t},\n\t\t\t\tHostname: \"localhost\",\n\t\t\t\tPorts:    []types.ServicePortConfig{}, // test empty array\n\t\t\t\tNetworks: map[string]*types.ServiceNetworkConfig{\n\t\t\t\t\t\"net1\": {},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"bar\": types.ServiceConfig{\n\t\t\t\tName:  \"bar\",\n\t\t\t\tImage: \"bar/foo\",\n\t\t\t\tBuild: &types.BuildConfig{\n\t\t\t\t\tContext: \"./build\",\n\t\t\t\t},\n\t\t\t\tHostname: \"localhost\",\n\t\t\t\tPorts:    []types.ServicePortConfig{}, // test empty array\n\t\t\t\tNetworks: map[string]*types.ServiceNetworkConfig{\n\t\t\t\t\t\"net1\": {},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tVolumes: types.Volumes{\n\t\t\t\"foo\": types.VolumeConfig{\n\t\t\t\tName:   \"foo\",\n\t\t\t\tDriver: \"storage\",\n\t\t\t},\n\t\t},\n\t}\n\n\tprojectWithDefaultNetwork := &types.Project{\n\t\tServices: types.Services{\n\t\t\t\"foo\": types.ServiceConfig{\n\t\t\t\tNetworks: map[string]*types.ServiceNetworkConfig{\n\t\t\t\t\t\"default\": {},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// define all test cases for checkUnsupportedKey function\n\ttestCases := map[string]struct {\n\t\tcomposeProject          *types.Project\n\t\texpectedUnsupportedKeys []string\n\t}{\n\t\t\"With Networks (service and root level)\": {\n\t\t\tprojectWithNetworks,\n\t\t\t//root level network and network are now supported\"\n\t\t\t[]string{\"root level volumes\"},\n\t\t},\n\t\t\"Default root level Network\": {\n\t\t\tprojectWithDefaultNetwork,\n\t\t\t[]string(nil),\n\t\t},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tkeys := checkUnsupportedKey(test.composeProject)\n\t\tif !reflect.DeepEqual(keys, test.expectedUnsupportedKeys) {\n\t\t\tt.Errorf(\"ERROR: Expecting unsupported keys: ['%s']. Got: ['%s']\", strings.Join(test.expectedUnsupportedKeys, \"', '\"), strings.Join(keys, \"', '\"))\n\t\t}\n\t}\n}\n\nfunc TestNormalizeServiceNames(t *testing.T) {\n\ttestCases := []struct {\n\t\tcomposeServiceName    string\n\t\tnormalizedServiceName string\n\t}{\n\t\t{\"foo_bar\", \"foo-bar\"},\n\t\t{\"foo\", \"foo\"},\n\t\t{\"foo.bar\", \"foo.bar\"},\n\t\t//{\"\", \"\"},\n\t}\n\n\tfor _, testCase := range testCases {\n\t\treturnValue := normalizeServiceNames(testCase.composeServiceName)\n\t\tif returnValue != testCase.normalizedServiceName {\n\t\t\tt.Logf(\"Expected %q, got %q\", testCase.normalizedServiceName, returnValue)\n\t\t}\n\t}\n}\n\nfunc TestNormalizeNetworkNames(t *testing.T) {\n\ttestCases := []struct {\n\t\tcomposeNetworkName    string\n\t\tnormalizedNetworkName string\n\t}{\n\t\t{\"foo_bar\", \"foo-bar\"},\n\t\t{\"foo\", \"foo\"},\n\t\t{\"FOO\", \"foo\"},\n\t\t{\"foo.bar\", \"foo.bar\"},\n\t\t//{\"\", \"\"},\n\t}\n\n\tfor _, testCase := range testCases {\n\t\treturnValue, err := normalizeNetworkNames(testCase.composeNetworkName)\n\t\tif err != nil {\n\t\t\tt.Log(\"Unexpected error, got \", err)\n\t\t}\n\t\tif returnValue != testCase.normalizedNetworkName {\n\t\t\tt.Logf(\"Expected %q, got %q\", testCase.normalizedNetworkName, returnValue)\n\t\t}\n\t}\n}\n\nfunc TestCheckPlacementCustomLabels(t *testing.T) {\n\tplacement := types.Placement{\n\t\tConstraints: []string{\n\t\t\t\"node.labels.something == anything\",\n\t\t\t\"node.labels.monitor != xxx\",\n\t\t},\n\t\tPreferences: []types.PlacementPreferences{\n\t\t\t{Spread: \"node.labels.zone\"},\n\t\t\t{Spread: \"foo\"},\n\t\t\t{Spread: \"node.labels.ssd\"},\n\t\t},\n\t}\n\toutput := loadPlacement(placement)\n\n\texpected := kobject.Placement{\n\t\tPositiveConstraints: map[string]string{\n\t\t\t\"something\": \"anything\",\n\t\t},\n\t\tNegativeConstraints: map[string]string{\n\t\t\t\"monitor\": \"xxx\",\n\t\t},\n\t\tPreferences: []string{\n\t\t\t\"zone\", \"ssd\",\n\t\t},\n\t}\n\n\tcheckConstraints(t, \"positive\", output.PositiveConstraints, expected.PositiveConstraints)\n\tcheckConstraints(t, \"negative\", output.NegativeConstraints, expected.NegativeConstraints)\n\n\tif len(output.Preferences) != len(expected.Preferences) {\n\t\tt.Errorf(\"preferences len is not equal, expected %d, got %d\", len(expected.Preferences), len(output.Preferences))\n\t}\n\tfor i := range output.Preferences {\n\t\tif output.Preferences[i] != expected.Preferences[i] {\n\t\t\tt.Errorf(\"preference is not equal, expected %s, got %s\", expected.Preferences[i], output.Preferences[i])\n\t\t}\n\t}\n}\n\nfunc checkConstraints(t *testing.T, caseName string, output, expected map[string]string) {\n\tt.Log(\"Test case:\", caseName)\n\tif len(output) != len(expected) {\n\t\tt.Errorf(\"constraints len is not equal, expected %d, got %d\", len(expected), len(output))\n\t}\n\tfor key := range output {\n\t\tif output[key] != expected[key] {\n\t\t\tt.Errorf(\"%s constraint is not equal, expected %s, got %s\", key, expected[key], output[key])\n\t\t}\n\t}\n}\n\nfunc Test_parseKomposeLabels(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tName:          \"name\",\n\t\tContainerName: \"containername\",\n\t\tImage:         \"image\",\n\t\tLabels:        nil,\n\t\tAnnotations:   map[string]string{\"abc\": \"def\"},\n\t\tRestart:       \"always\",\n\t}\n\n\ttype args struct {\n\t\tlabels        types.Labels\n\t\tserviceConfig *kobject.ServiceConfig\n\t}\n\ttests := []struct {\n\t\tname     string\n\t\targs     args\n\t\texpected *kobject.ServiceConfig\n\t}{\n\t\t{\n\t\t\tname: \"override with overriding\",\n\t\t\targs: args{\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\tLabelNameOverride: \"overriding\",\n\t\t\t\t},\n\t\t\t\tserviceConfig: &service,\n\t\t\t},\n\t\t\texpected: &kobject.ServiceConfig{\n\t\t\t\tName: \"overriding\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"override\",\n\t\t\targs: args{\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\tLabelNameOverride: \"overriding-resource-name\",\n\t\t\t\t},\n\t\t\t\tserviceConfig: &service,\n\t\t\t},\n\t\t\texpected: &kobject.ServiceConfig{\n\t\t\t\tName: \"overriding-resource-name\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"hyphen in the middle\",\n\t\t\targs: args{\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\tLabelNameOverride: \"overriding_resource-name\",\n\t\t\t\t},\n\t\t\t\tserviceConfig: &service,\n\t\t\t},\n\t\t\texpected: &kobject.ServiceConfig{\n\t\t\t\tName: \"overriding-resource-name\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"hyphen in the middle with mays\",\n\t\t\targs: args{\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\tLabelNameOverride: \"OVERRIDING_RESOURCE-NAME\",\n\t\t\t\t},\n\t\t\t\tserviceConfig: &service,\n\t\t\t},\n\t\t\texpected: &kobject.ServiceConfig{\n\t\t\t\tName: \"overriding-resource-name\",\n\t\t\t},\n\t\t},\n\t\t// This is a corner case that is expected to fail because\n\t\t// it does not account for scenarios where the string\n\t\t// starts or ends with a '-' or any other character\n\t\t// this test will fail with current tests\n\t\t// {\n\t\t// \tname: \"Add a prefix with a dash at the start and end, with a hyphen in the middle.\",\n\t\t// \targs: args{\n\t\t// \t\tlabels: types.Labels{\n\t\t// \t\t\tLabelNameOverride: \"-OVERRIDING_RESOURCE-NAME-\",\n\t\t// \t\t},\n\t\t// \t\tserviceConfig: &service,\n\t\t// \t},\n\t\t// \texpected: &kobject.ServiceConfig{\n\t\t// \t\tName: \"overriding-resource-name\",\n\t\t// \t},\n\t\t// },\n\t\t// not fail\n\t\t{\n\t\t\tname: \"Add a prefix with a dash at the start and end, with a hyphen in the middle.\",\n\t\t\targs: args{\n\t\t\t\tlabels: types.Labels{\n\t\t\t\t\tLabelNameOverride: \"-OVERRIDING_RESOURCE-NAME-\",\n\t\t\t\t},\n\t\t\t\tserviceConfig: &service,\n\t\t\t},\n\t\t\texpected: &kobject.ServiceConfig{\n\t\t\t\tName: \"-overriding-resource-name-\",\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif err := parseKomposeLabels(tt.args.labels, tt.args.serviceConfig); err != nil {\n\t\t\t\tt.Errorf(\"parseKomposeLabels(): %v\", err)\n\t\t\t}\n\n\t\t\tif tt.expected.Name != tt.args.serviceConfig.Name {\n\t\t\t\tt.Errorf(\"Name are not equal, expected: %v, output: %v\", tt.expected.Name, tt.args.serviceConfig.Name)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/loader/compose/utils.go",
    "content": "/*\nCopyright 2017 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\nhttp://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*/\n\npackage compose\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/pkg/errors\"\n\n\tapi \"k8s.io/api/core/v1\"\n)\n\nconst (\n\t// LabelServiceType defines the type of service to be created\n\tLabelServiceType = \"kompose.service.type\"\n\t// LabelServiceExternalTrafficPolicy defines the external policy traffic of service to be created\n\tLabelServiceExternalTrafficPolicy = \"kompose.service.external-traffic-policy\"\n\t// LabelServiceGroup defines the group of services in a single pod\n\tLabelServiceGroup = \"kompose.service.group\"\n\t// LabelNodePortPort defines the port value for NodePort service\n\tLabelNodePortPort = \"kompose.service.nodeport.port\"\n\t// LabelServiceExpose defines if the service needs to be made accessible from outside the cluster or not\n\tLabelServiceExpose = \"kompose.service.expose\"\n\t// LabelServiceExposeTLSSecret provides the name of the TLS secret to use with the Kubernetes ingress controller\n\tLabelServiceExposeTLSSecret = \"kompose.service.expose.tls-secret\"\n\t// LabelServiceExposeIngressClassName provides the name of ingress class to use with the Kubernetes ingress controller\n\tLabelServiceExposeIngressClassName = \"kompose.service.expose.ingress-class-name\"\n\t// LabelServiceAccountName defines the service account name to provide the credential info of the pod.\n\tLabelServiceAccountName = \"kompose.serviceaccount-name\"\n\t// LabelControllerType defines the type of controller to be created\n\tLabelControllerType = \"kompose.controller.type\"\n\t// LabelImagePullSecret defines a secret name for kubernetes ImagePullSecrets\n\tLabelImagePullSecret = \"kompose.image-pull-secret\"\n\t// LabelImagePullPolicy defines Kubernetes PodSpec imagePullPolicy.\n\tLabelImagePullPolicy = \"kompose.image-pull-policy\"\n\t// HealthCheckReadinessDisable defines readiness health check disable\n\tHealthCheckReadinessDisable = \"kompose.service.healthcheck.readiness.disable\"\n\t// HealthCheckReadinessTest defines readiness health check test\n\tHealthCheckReadinessTest = \"kompose.service.healthcheck.readiness.test\"\n\t// HealthCheckReadinessInterval defines readiness health check interval\n\tHealthCheckReadinessInterval = \"kompose.service.healthcheck.readiness.interval\"\n\t// HealthCheckReadinessTimeout defines readiness health check timeout\n\tHealthCheckReadinessTimeout = \"kompose.service.healthcheck.readiness.timeout\"\n\t// HealthCheckReadinessRetries defines readiness health check retries\n\tHealthCheckReadinessRetries = \"kompose.service.healthcheck.readiness.retries\"\n\t// HealthCheckReadinessStartPeriod defines readiness health check start period\n\tHealthCheckReadinessStartPeriod = \"kompose.service.healthcheck.readiness.start_period\"\n\t// HealthCheckReadinessHTTPGetPath defines readiness health check HttpGet path\n\tHealthCheckReadinessHTTPGetPath = \"kompose.service.healthcheck.readiness.http_get_path\"\n\t// HealthCheckReadinessHTTPGetPort defines readiness health check HttpGet port\n\tHealthCheckReadinessHTTPGetPort = \"kompose.service.healthcheck.readiness.http_get_port\"\n\t// HealthCheckReadinessTCPPort defines readiness health check tcp port\n\tHealthCheckReadinessTCPPort = \"kompose.service.healthcheck.readiness.tcp_port\"\n\t// HealthCheckLivenessHTTPGetPath defines liveness health check HttpGet path\n\tHealthCheckLivenessHTTPGetPath = \"kompose.service.healthcheck.liveness.http_get_path\"\n\t// HealthCheckLivenessHTTPGetPort defines liveness health check HttpGet port\n\tHealthCheckLivenessHTTPGetPort = \"kompose.service.healthcheck.liveness.http_get_port\"\n\t// HealthCheckLivenessTCPPort defines liveness health check tcp port\n\tHealthCheckLivenessTCPPort = \"kompose.service.healthcheck.liveness.tcp_port\"\n\t// ServiceTypeHeadless ...\n\tServiceTypeHeadless = \"Headless\"\n\t// LabelSecurityContextFsGroup defines the pod FsGroup\n\tLabelSecurityContextFsGroup = \"kompose.security-context.fsgroup\"\n\t// LabelContainerVolumeSubpath defines the volume mount subpath inside container\n\tLabelContainerVolumeSubpath = \"kompose.volume.subpath\"\n\t// LabelCronJobSchedule defines the cron job schedule\n\tLabelCronJobSchedule = \"kompose.cronjob.schedule\"\n\t// LabelCronJobConcurrencyPolicy defines the cron job concurrency policy\n\tLabelCronJobConcurrencyPolicy = \"kompose.cronjob.concurrency_policy\"\n\t// LabelCronJobBackoffLimit defines the job backoff limit\n\tLabelCronJobBackoffLimit = \"kompose.cronjob.backoff_limit\"\n\t// LabelInitContainerName defines name resource\n\tLabelInitContainerName = \"kompose.init.containers.name\"\n\t// LabelInitContainerImage defines image to pull\n\tLabelInitContainerImage = \"kompose.init.containers.image\"\n\t// LabelInitContainerCommand defines commands\n\tLabelInitContainerCommand = \"kompose.init.containers.command\"\n\t// LabelHpaMinReplicas defines min pod replicas\n\tLabelHpaMinReplicas = \"kompose.hpa.replicas.min\"\n\t// LabelHpaMaxReplicas defines max pod replicas\n\tLabelHpaMaxReplicas = \"kompose.hpa.replicas.max\"\n\t// LabelHpaCpu defines scaling decisions based on CPU utilization\n\tLabelHpaCPU = \"kompose.hpa.cpu\"\n\t// LabelHpaMemory defines scaling decisions based on memory utilization\n\tLabelHpaMemory = \"kompose.hpa.memory\"\n\t// LabelNameOverride defines the override resource name\n\tLabelNameOverride = \"kompose.service.name_override\"\n\t// LabelExposeContainerToHost defines whether to expose container to host or not using hostPort\n\tLabelExposeContainerToHost = \"kompose.controller.port.expose\"\n)\n\n// load environment variables from compose file\nfunc loadEnvVars(envars []string) []kobject.EnvVar {\n\tenvs := []kobject.EnvVar{}\n\tfor _, e := range envars {\n\t\tcharacter := \"\"\n\t\tequalPos := strings.Index(e, \"=\")\n\t\tcolonPos := strings.Index(e, \":\")\n\t\tswitch {\n\t\tcase equalPos == -1 && colonPos == -1:\n\t\t\tcharacter = \"\"\n\t\tcase equalPos == -1 && colonPos != -1:\n\t\t\tcharacter = \":\"\n\t\tcase equalPos != -1 && colonPos == -1:\n\t\t\tcharacter = \"=\"\n\t\tcase equalPos != -1 && colonPos != -1:\n\t\t\tif equalPos > colonPos {\n\t\t\t\tcharacter = \":\"\n\t\t\t} else {\n\t\t\t\tcharacter = \"=\"\n\t\t\t}\n\t\t}\n\n\t\tif character == \"\" {\n\t\t\tenvs = append(envs, kobject.EnvVar{\n\t\t\t\tName:  e,\n\t\t\t\tValue: os.Getenv(e),\n\t\t\t})\n\t\t} else {\n\t\t\tvalues := strings.SplitN(e, character, 2)\n\t\t\t// try to get value from os env\n\t\t\tif values[1] == \"\" {\n\t\t\t\tvalues[1] = os.Getenv(values[0])\n\t\t\t}\n\t\t\tenvs = append(envs, kobject.EnvVar{\n\t\t\t\tName:  values[0],\n\t\t\t\tValue: values[1],\n\t\t\t})\n\t\t}\n\t}\n\n\treturn envs\n}\n\nfunc handleServiceType(ServiceType string) (string, error) {\n\tswitch strings.ToLower(ServiceType) {\n\tcase \"\", \"clusterip\":\n\t\treturn string(api.ServiceTypeClusterIP), nil\n\tcase \"nodeport\":\n\t\treturn string(api.ServiceTypeNodePort), nil\n\tcase \"loadbalancer\":\n\t\treturn string(api.ServiceTypeLoadBalancer), nil\n\tcase \"headless\":\n\t\treturn ServiceTypeHeadless, nil\n\tdefault:\n\t\treturn \"\", errors.New(\"Unknown value \" + ServiceType + \" , supported values are 'nodeport, clusterip, headless or loadbalancer'\")\n\t}\n}\n\nfunc handleServiceExternalTrafficPolicy(ServiceExternalTrafficPolicyType string) (string, error) {\n\tswitch strings.ToLower(ServiceExternalTrafficPolicyType) {\n\tcase \"\", \"cluster\":\n\t\treturn string(api.ServiceExternalTrafficPolicyTypeCluster), nil\n\tcase \"local\":\n\t\treturn string(api.ServiceExternalTrafficPolicyTypeLocal), nil\n\tdefault:\n\t\treturn \"\", errors.New(\"Unknown value \" + ServiceExternalTrafficPolicyType + \" , supported values are 'local, cluster'\")\n\t}\n}\n\nfunc normalizeContainerNames(svcName string) string {\n\treturn strings.ToLower(svcName)\n}\n\nfunc normalizeServiceNames(svcName string) string {\n\tre := regexp.MustCompile(\"[._]\")\n\treturn strings.ToLower(re.ReplaceAllString(svcName, \"-\"))\n}\n\nfunc normalizeVolumes(svcName string) string {\n\treturn strings.Replace(svcName, \"_\", \"-\", -1)\n}\n\nfunc normalizeNetworkNames(netName string) (string, error) {\n\tnetval := strings.ToLower(strings.Replace(netName, \"_\", \"-\", -1))\n\tregString := \"[^A-Za-z0-9.-]+\"\n\treg, err := regexp.Compile(regString)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tnetval = reg.ReplaceAllString(netval, \"\")\n\treturn netval, nil\n}\n\n// ReadFile read data from file or stdin\nfunc ReadFile(fileName string) ([]byte, error) {\n\tif fileName == \"-\" {\n\t\tif StdinData == nil {\n\t\t\tdata, err := io.ReadAll(os.Stdin)\n\t\t\tStdinData = data\n\t\t\treturn data, err\n\t\t}\n\t\treturn StdinData, nil\n\t}\n\treturn os.ReadFile(fileName)\n}\n\n// Choose normalized name from resource in case exist LabelNameOverride\n// from label\nfunc parseResourceName(resourceName string, labels types.Labels) string {\n\t// Opted to use normalizeContainerNames over normalizeServiceNames\n\t// as in tests, normalization is only to lowercase.\n\tnormalizedName := normalizeContainerNames(resourceName)\n\tif labelValue, exist := labels[LabelNameOverride]; exist {\n\t\tnormalizedName = normalizeContainerNames(labelValue)\n\t}\n\treturn normalizedName\n}\n"
  },
  {
    "path": "pkg/loader/loader.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage loader\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/loader/compose\"\n)\n\n// Loader interface defines loader that loads files and converts it to kobject representation\ntype Loader interface {\n\tLoadFile(files []string, profiles []string, noInterpolate bool) (kobject.KomposeObject, error)\n\t///Name() string\n}\n\n// GetLoader returns loader for given format\nfunc GetLoader(format string) (Loader, error) {\n\tif format != \"compose\" {\n\t\treturn nil, fmt.Errorf(\"input file format %s is not supported\", format)\n\t}\n\treturn new(compose.Compose), nil\n}\n"
  },
  {
    "path": "pkg/snap/snapcraft.yaml",
    "content": "name: kompose\nsummary:  Go from Docker Compose to Kubernetes.\ndescription:Kompose is a tool to help users who are familiar with docker-compose move to Kubernetes. kompose takes a Docker Compose file and translates it into Kubernetes resources.\n  \ngrade: stable\nconfinement: classic\n\narchitectures:\n  - build-on: i386\n  - build-on: amd64\n  - build-on: armhf\n  - build-on: arm64\n\napps:\n  kompose:\n    command: bin/kompose\n    plugs:\n      - home\n      - network\n      - docker\n      - removable-media\n\nparts:\n  kompose:\n  plugin: nil \n    source: https://github.com/kubernetes/kompose.git\n    source-type: git\n    override-pull: |\n      git clone https://github.com/kubernetes/kompose.git src/github.com/kubernetes/kompose\n      cd src/github.com/kubernetes/kompose\n      last_committed_tag=\"$(git describe --tags --abbrev=0)\"\n      last_committed_tag_ver=\"$(echo ${last_committed_tag} | sed 's/v//')\"\n      last_released_tag=\"$(snap info $SNAPCRAFT_PROJECT_NAME | awk '$1 == \"beta:\" { print $2 }')\"\n      # If the latest tag from the upstream project has not been released to\n      # beta, build that tag instead of master.\n      if [ \"${last_committed_tag_ver}\" != \"${last_released_tag}\" ]; then\n        git fetch\n        git checkout \"${last_committed_tag}\"\n        fi\n      snapcraftctl set-version \"$(git describe --tags | sed 's/v//')\"\n      override-build: |\n      export GOPATH=$PWD\n      cd src/github.com/kubernetes/kompose\n      env CGO_ENABLED=0 GOOS=linux \\\n      go build --ldflags \"-s -w \\\n        -X 'github.com/kubernetes/kompose/version.GitCommit=$(git rev-list -1 HEAD)' \\\n        -X 'github.com/kubernetes/kompose/version.Version=$(git describe --tags --abbrev=0)'\" \\\n        -a -installsuffix cgo -o $SNAPCRAFT_PART_INSTALL/bin/kompose\n    build-snaps:\n      - go\n    build-packages:\n      - git\n      - sed\n"
  },
  {
    "path": "pkg/testutils/git.go",
    "content": "package testutils\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"testing\"\n)\n\n// NewCommand TODO: comment\nfunc NewCommand(cmd string) *exec.Cmd {\n\treturn exec.Command(\"sh\", \"-c\", cmd)\n}\n\n// CreateLocalDirectory TODO: comment\nfunc CreateLocalDirectory(t *testing.T) string {\n\tdir, err := os.MkdirTemp(os.TempDir(), \"kompose-test-\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn dir\n}\n\n// CreateLocalGitDirectory TODO: comment\nfunc CreateLocalGitDirectory(t *testing.T) string {\n\tdir := CreateLocalDirectory(t)\n\tcmd := NewCommand(\n\t\t`git init &&\n\t\t git config  user.email \"you@example.com\" &&\n\t\t git config  user.name \"Your Name\" &&\n\t\t touch README &&\n\t\t git add README &&\n\t\t git commit --no-gpg-sign -m 'testcommit'`)\n\tcmd.Dir = dir\n\t_, err := cmd.Output()\n\tif err != nil {\n\t\tt.Logf(\"create local git dir: %v\", err)\n\t\tt.Fatal(err)\n\t}\n\treturn dir\n}\n\n// SetGitRemote TODO: comment\nfunc SetGitRemote(t *testing.T, dir string, remote string, remoteURL string) {\n\tcmd := NewCommand(fmt.Sprintf(\"git remote add %s %s\", remote, remoteURL))\n\tcmd.Dir = dir\n\t_, err := cmd.Output()\n\tif err != nil {\n\t\tt.Logf(\"set git remote: %v\", err)\n\t\tt.Fatal(err)\n\t}\n}\n\n// CreateGitRemoteBranch TODO: comment\nfunc CreateGitRemoteBranch(t *testing.T, dir string, branch string, remote string) {\n\tcmd := NewCommand(\n\t\tfmt.Sprintf(`git checkout -b %s &&\n\t\t    git config branch.%s.remote %s &&\n\t\t \tgit config branch.%s.merge refs/heads/%s`,\n\t\t\tbranch, branch, remote, branch, branch))\n\tcmd.Dir = dir\n\n\t_, err := cmd.Output()\n\tif err != nil {\n\t\tt.Logf(\"create git branch: %v\", err)\n\t\tt.Fatal(err)\n\t}\n}\n\n// CreateSubdir TODO: comment\nfunc CreateSubdir(t *testing.T, dir string, subdir string) {\n\tcmd := NewCommand(fmt.Sprintf(\"mkdir -p %s\", subdir))\n\tcmd.Dir = dir\n\n\t_, err := cmd.Output()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "pkg/testutils/kubernetes.go",
    "content": "package testutils\n\nimport (\n\t\"errors\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// CheckForHeadless is helper function for tests.\n// It checks if all Services in objects are Headless Services and if there is at least one such Services.\nfunc CheckForHeadless(objects []runtime.Object) error {\n\tserviceCreated := false\n\tfor _, obj := range objects {\n\t\tif svc, ok := obj.(*v1.Service); ok {\n\t\t\tserviceCreated = true\n\t\t\t// Check if it is a headless services\n\t\t\tif svc.Spec.ClusterIP != \"None\" {\n\t\t\t\treturn errors.New(\"this is not a Headless services\")\n\t\t\t}\n\t\t}\n\t}\n\tif !serviceCreated {\n\t\treturn errors.New(\"no Service created\")\n\t}\n\treturn nil\n}\n\n// CheckForHealthCheckLivenessAndReadiness check if has liveness and readiness in healthcheck configured.\nfunc CheckForHealthCheckLivenessAndReadiness(objects []runtime.Object) error {\n\tserviceCreated := false\n\tfor _, obj := range objects {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tserviceCreated = true\n\n\t\t\t// Check if it is a headless services\n\t\t\tif deployment.Spec.Template.Spec.Containers[0].ReadinessProbe == nil {\n\t\t\t\treturn errors.New(\"there is not a ReadinessProbe\")\n\t\t\t}\n\t\t\tif deployment.Spec.Template.Spec.Containers[0].LivenessProbe == nil {\n\t\t\t\treturn errors.New(\"there is not a LivenessGate\")\n\t\t\t}\n\t\t}\n\t}\n\tif !serviceCreated {\n\t\treturn errors.New(\"no Service created\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/transformer/kubernetes/k8sutils.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage kubernetes\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/template\"\n\t\"time\"\n\n\t\"github.com/compose-spec/compose-go/v2/dotenv\"\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\t\"github.com/joho/godotenv\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/loader/compose\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\tdeployapi \"github.com/openshift/api/apps/v1\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"gopkg.in/yaml.v3\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\thpa \"k8s.io/api/autoscaling/v2beta2\"\n\tapi \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/resource\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// Default values for Horizontal Pod Autoscaler (HPA)\nconst (\n\tDefaultMinReplicas       = 1\n\tDefaultMaxReplicas       = 3\n\tDefaultCPUUtilization    = 50\n\tDefaultMemoryUtilization = 70\n)\n\n// LabelKeys are the keys for HPA related labels in the service\nvar LabelKeys = []string{\n\tcompose.LabelHpaCPU,\n\tcompose.LabelHpaMemory,\n\tcompose.LabelHpaMinReplicas,\n\tcompose.LabelHpaMaxReplicas,\n}\n\ntype HpaValues struct {\n\tMinReplicas       int32\n\tMaxReplicas       int32\n\tCPUtilization     int32\n\tMemoryUtilization int32\n}\n\nconst (\n\tNetworkModeService = \"service:\"\n)\n\ntype DeploymentMapping struct {\n\tSourceDeploymentName string\n\tTargetDeploymentName string\n}\n\n/**\n * Generate Helm Chart configuration\n */\nfunc generateHelm(dirName string) error {\n\ttype ChartDetails struct {\n\t\tName string\n\t}\n\n\tdetails := ChartDetails{dirName}\n\tmanifestDir := dirName + string(os.PathSeparator) + \"templates\"\n\tdir, err := os.Open(dirName)\n\n\t/* Setup the initial directories/files */\n\tif err == nil {\n\t\t_ = dir.Close()\n\t}\n\n\tif err != nil {\n\t\terr = os.Mkdir(dirName, 0755)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\terr = os.Mkdir(manifestDir, 0755)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t/* Create the readme file */\n\treadme := \"This chart was created by Kompose\\n\"\n\terr = os.WriteFile(dirName+string(os.PathSeparator)+\"README.md\", []byte(readme), 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t/* Create the Chart.yaml file */\n\tchart := `name: {{.Name}}\ndescription: A generated Helm Chart for {{.Name}} from Skippbox Kompose\nversion: 0.0.1\napiVersion: v2\nkeywords:\n  - {{.Name}}\nsources:\nhome:\n`\n\n\tt, err := template.New(\"ChartTmpl\").Parse(chart)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to generate Chart.yaml template, template.New failed\")\n\t}\n\tvar chartData bytes.Buffer\n\t_ = t.Execute(&chartData, details)\n\n\terr = os.WriteFile(dirName+string(os.PathSeparator)+\"Chart.yaml\", chartData.Bytes(), 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Infof(\"chart created in %q\\n\", dirName+string(os.PathSeparator))\n\treturn nil\n}\n\n// Check if given path is a directory\nfunc isDir(name string) (bool, error) {\n\t// Open file to get stat later\n\tf, err := os.Open(name)\n\tif err != nil {\n\t\treturn false, nil\n\t}\n\tdefer f.Close()\n\n\t// Get file attributes and information\n\tfileStat, err := f.Stat()\n\tif err != nil {\n\t\treturn false, errors.Wrap(err, \"error retrieving file information, f.Stat failed\")\n\t}\n\n\t// Check if given path is a directory\n\tif fileStat.IsDir() {\n\t\treturn true, nil\n\t}\n\treturn false, nil\n}\n\nfunc getDirName(opt kobject.ConvertOptions) string {\n\tdirName := opt.OutFile\n\tif dirName == \"\" {\n\t\t// Let assume all the docker-compose files are in the same directory\n\t\tif opt.CreateChart {\n\t\t\tfilename := opt.InputFiles[0]\n\t\t\textension := filepath.Ext(filename)\n\t\t\tdirName = filename[0 : len(filename)-len(extension)]\n\t\t} else {\n\t\t\tdirName = \".\"\n\t\t}\n\t}\n\treturn dirName\n}\n\n// PrintList will take the data converted and decide on the commandline attributes given\nfunc PrintList(objects []runtime.Object, opt kobject.ConvertOptions) error {\n\tvar f *os.File\n\tdirName := getDirName(opt)\n\tlog.Debugf(\"Target Dir: %s\", dirName)\n\n\t// Create a directory if \"out\" ends with \"/\" and does not exist.\n\tif !transformer.Exists(opt.OutFile) && strings.HasSuffix(opt.OutFile, \"/\") {\n\t\tif err := os.MkdirAll(opt.OutFile, os.ModePerm); err != nil {\n\t\t\treturn errors.Wrap(err, \"failed to create a directory\")\n\t\t}\n\t}\n\n\t// Check if output file is a directory\n\tisDirVal, err := isDir(opt.OutFile)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"isDir failed\")\n\t}\n\tif opt.CreateChart {\n\t\tisDirVal = true\n\t}\n\tif !isDirVal {\n\t\tf, err = transformer.CreateOutFile(opt.OutFile)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"transformer.CreateOutFile failed\")\n\t\t}\n\t\tif len(opt.OutFile) != 0 {\n\t\t\tlog.Printf(\"Kubernetes file %q created\", opt.OutFile)\n\t\t}\n\t\tdefer f.Close()\n\t}\n\n\tvar files []string\n\t// if asked to print to stdout or to put in single file\n\t// we will create a list\n\tif opt.ToStdout || f != nil {\n\t\t// convert objects to versioned and add them to list\n\t\tif opt.GenerateJSON {\n\t\t\treturn fmt.Errorf(\"cannot convert to one file while specifying a json output file or stdout option\")\n\t\t}\n\t\tfor _, object := range objects {\n\t\t\tversionedObject, err := convertToVersion(object)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tdata, err := marshal(versionedObject, opt.GenerateJSON, opt.YAMLIndent)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error in marshalling the List: %v\", err)\n\t\t\t}\n\t\t\t// this part add --- which unifies the file\n\t\t\tdata = []byte(fmt.Sprintf(\"---\\n%s\", data))\n\t\t\tprintVal, err := transformer.Print(\"\", dirName, \"\", data, opt.ToStdout, opt.GenerateJSON, f, opt.Provider)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"transformer to print to one single file failed\")\n\t\t\t}\n\t\t\tfiles = append(files, printVal)\n\t\t}\n\t} else {\n\t\tfinalDirName := dirName\n\t\tif opt.CreateChart {\n\t\t\tfinalDirName = dirName + string(os.PathSeparator) + \"templates\"\n\t\t}\n\n\t\tif err := os.MkdirAll(finalDirName, 0755); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tvar file string\n\t\t// create a separate file for each provider\n\t\tfor _, v := range objects {\n\t\t\tversionedObject, err := convertToVersion(v)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdata, err := marshal(versionedObject, opt.GenerateJSON, opt.YAMLIndent)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tvar typeMeta metav1.TypeMeta\n\t\t\tvar objectMeta metav1.ObjectMeta\n\n\t\t\tif us, ok := v.(*unstructured.Unstructured); ok {\n\t\t\t\ttypeMeta = metav1.TypeMeta{\n\t\t\t\t\tKind:       us.GetKind(),\n\t\t\t\t\tAPIVersion: us.GetAPIVersion(),\n\t\t\t\t}\n\t\t\t\tobjectMeta = metav1.ObjectMeta{\n\t\t\t\t\tName: us.GetName(),\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval := reflect.ValueOf(v).Elem()\n\t\t\t\t// Use reflect to access TypeMeta struct inside runtime.Object.\n\t\t\t\t// cast it to correct type - metav1.TypeMeta\n\t\t\t\ttypeMeta = val.FieldByName(\"TypeMeta\").Interface().(metav1.TypeMeta)\n\n\t\t\t\t// Use reflect to access ObjectMeta struct inside runtime.Object.\n\t\t\t\t// cast it to correct type - api.ObjectMeta\n\t\t\t\tobjectMeta = val.FieldByName(\"ObjectMeta\").Interface().(metav1.ObjectMeta)\n\t\t\t}\n\n\t\t\tfile, err = transformer.Print(objectMeta.Name, finalDirName, strings.ToLower(typeMeta.Kind), data, opt.ToStdout, opt.GenerateJSON, f, opt.Provider)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"transformer.Print failed\")\n\t\t\t}\n\n\t\t\tfiles = append(files, file)\n\t\t}\n\t}\n\tif opt.CreateChart {\n\t\terr = generateHelm(dirName)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"generateHelm failed\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// marshal object runtime.Object and return byte array\nfunc marshal(obj runtime.Object, jsonFormat bool, indent int) (data []byte, err error) {\n\t// convert data to yaml or json\n\tif jsonFormat {\n\t\tdata, err = json.MarshalIndent(obj, \"\", \"  \")\n\t} else {\n\t\tdata, err = marshalWithIndent(obj, indent)\n\t}\n\tif err != nil {\n\t\tdata = nil\n\t}\n\treturn\n}\n\n// remove empty map[string]interface{} strings from the object\n//\n// Note: this function uses recursion, use it only objects created by the unmarshalled json.\n// Passing cyclic structures to removeEmptyInterfaces will result in a stack overflow.\nfunc removeEmptyInterfaces(obj interface{}) interface{} {\n\tswitch v := obj.(type) {\n\tcase []interface{}:\n\t\tfor i, val := range v {\n\t\t\tif valMap, ok := val.(map[string]interface{}); (ok && len(valMap) == 0) || val == nil {\n\t\t\t\tv = append(v[:i], v[i+1:]...)\n\t\t\t} else {\n\t\t\t\tv[i] = removeEmptyInterfaces(val)\n\t\t\t}\n\t\t}\n\t\treturn v\n\tcase map[string]interface{}:\n\t\tfor k, val := range v {\n\t\t\tif valMap, ok := val.(map[string]interface{}); ok {\n\t\t\t\t// It is always map[string]interface{} when passed the map[string]interface{}\n\t\t\t\tvalMap := removeEmptyInterfaces(valMap).(map[string]interface{})\n\t\t\t\tif len(valMap) == 0 {\n\t\t\t\t\tdelete(v, k)\n\t\t\t\t}\n\t\t\t} else if val == nil {\n\t\t\t\tdelete(v, k)\n\t\t\t} else {\n\t\t\t\tprocessedInterface := removeEmptyInterfaces(val)\n\t\t\t\tif valSlice, ok := processedInterface.([]interface{}); ok && len(valSlice) == 0 {\n\t\t\t\t\tdelete(v, k)\n\t\t\t\t} else {\n\t\t\t\t\tv[k] = processedInterface\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn v\n\tdefault:\n\t\treturn v\n\t}\n}\n\n// Convert JSON to YAML.\nfunc jsonToYaml(j []byte, spaces int) ([]byte, error) {\n\t// Convert the JSON to an object.\n\tvar jsonObj interface{}\n\t// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the\n\t// Go JSON library doesn't try to pick the right number type (int, float,\n\t// etc.) when unmarshling to interface{}, it just picks float64\n\t// universally. go-yaml does go through the effort of picking the right\n\t// number type, so we can preserve number type throughout this process.\n\terr := yaml.Unmarshal(j, &jsonObj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tjsonObj = removeEmptyInterfaces(jsonObj)\n\tvar b bytes.Buffer\n\tencoder := yaml.NewEncoder(&b)\n\tencoder.SetIndent(spaces)\n\tif err := encoder.Encode(jsonObj); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b.Bytes(), nil\n\n\t// Marshal this object into YAML.\n\t// return yaml.Marshal(jsonObj)\n}\n\nfunc marshalWithIndent(o interface{}, indent int) ([]byte, error) {\n\tj, err := json.Marshal(o)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error marshaling into JSON: %s\", err.Error())\n\t}\n\n\ty, err := jsonToYaml(j, indent)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error converting JSON to YAML: %s\", err.Error())\n\t}\n\n\treturn y, nil\n}\n\n// Convert object to versioned object\n// if groupVersion is  empty (metav1.GroupVersion{}), use version from original object (obj)\nfunc convertToVersion(obj runtime.Object) (runtime.Object, error) {\n\t// ignore unstruct object\n\tif _, ok := obj.(*unstructured.Unstructured); ok {\n\t\treturn obj, nil\n\t}\n\n\treturn obj, nil\n\n\t//var version metav1.GroupVersion\n\t//\n\t//if groupVersion.Empty() {\n\t//\tobjectVersion := obj.GetObjectKind().GroupVersionKind()\n\t//\tversion = metav1.GroupVersion{Group: objectVersion.Group, Version: objectVersion.Version}\n\t//} else {\n\t//\tversion = groupVersion\n\t//}\n\t//convertedObject, err := api.Scheme.ConvertToVersion(obj, version)\n\t//if err != nil {\n\t//\treturn nil, err\n\t//}\n\t//return convertedObject, nil\n}\n\n// PortsExist checks if service has ports defined\nfunc (k *Kubernetes) PortsExist(service kobject.ServiceConfig) bool {\n\treturn len(service.Port) != 0\n}\n\nfunc (k *Kubernetes) initSvcObject(name string, service kobject.ServiceConfig, ports []api.ServicePort) *api.Service {\n\tsvc := k.InitSvc(name, service)\n\t// special case, only for loaderbalancer type\n\tsvc.Name = name\n\tsvc.Spec.Selector = transformer.ConfigLabels(service.Name)\n\n\tsvc.Spec.Ports = ports\n\tsvc.Spec.Type = api.ServiceType(service.ServiceType)\n\n\t// Configure annotations\n\tannotations := transformer.ConfigAnnotations(service)\n\tsvc.ObjectMeta.Annotations = annotations\n\n\treturn svc\n}\n\n// CreateLBService creates a k8s Load Balancer Service\nfunc (k *Kubernetes) CreateLBService(name string, service kobject.ServiceConfig) []*api.Service {\n\tvar svcs []*api.Service\n\ttcpPorts, udpPorts := k.ConfigLBServicePorts(service)\n\tif tcpPorts != nil {\n\t\tsvc := k.initSvcObject(name+\"-tcp\", service, tcpPorts)\n\t\tsvcs = append(svcs, svc)\n\t}\n\tif udpPorts != nil {\n\t\tsvc := k.initSvcObject(name+\"-udp\", service, udpPorts)\n\t\tsvcs = append(svcs, svc)\n\t}\n\treturn svcs\n}\n\n// CreateService creates a k8s service\nfunc (k *Kubernetes) CreateService(name string, service kobject.ServiceConfig) *api.Service {\n\tsvc := k.InitSvc(name, service)\n\n\t// Configure the service ports.\n\tservicePorts := k.ConfigServicePorts(service)\n\tsvc.Spec.Ports = servicePorts\n\n\tif service.ServiceType == \"Headless\" {\n\t\tsvc.Spec.Type = api.ServiceTypeClusterIP\n\t\tsvc.Spec.ClusterIP = \"None\"\n\t} else {\n\t\tsvc.Spec.Type = api.ServiceType(service.ServiceType)\n\t}\n\n\t// Configure annotations\n\tannotations := transformer.ConfigAnnotations(service)\n\tsvc.ObjectMeta.Annotations = annotations\n\n\treturn svc\n}\n\n// CreateHeadlessService creates a k8s headless service.\n// This is used for docker-compose services without ports. For such services we can't create regular Kubernetes Service.\n// and without Service Pods can't find each other using DNS names.\n// Instead of regular Kubernetes Service we create Headless Service. DNS of such service points directly to Pod IP address.\n// You can find more about Headless Services in Kubernetes documentation https://kubernetes.io/docs/user-guide/services/#headless-services\nfunc (k *Kubernetes) CreateHeadlessService(name string, service kobject.ServiceConfig) *api.Service {\n\tsvc := k.InitSvc(name, service)\n\n\tvar servicePorts []api.ServicePort\n\t// Configure a dummy port: https://github.com/kubernetes/kubernetes/issues/32766.\n\tservicePorts = append(servicePorts, api.ServicePort{\n\t\tName: \"headless\",\n\t\tPort: 55555,\n\t})\n\n\tsvc.Spec.Ports = servicePorts\n\tsvc.Spec.ClusterIP = \"None\"\n\n\t// Configure annotations\n\tannotations := transformer.ConfigAnnotations(service)\n\tsvc.ObjectMeta.Annotations = annotations\n\n\treturn svc\n}\n\n// UpdateKubernetesObjectsMultipleContainers method updates the kubernetes objects with the necessary data\nfunc (k *Kubernetes) UpdateKubernetesObjectsMultipleContainers(name string, service kobject.ServiceConfig, objects *[]runtime.Object, podSpec PodSpec, opt kobject.ConvertOptions) error {\n\t// Configure annotations\n\tannotations := transformer.ConfigAnnotations(service)\n\n\t// fillTemplate fills the pod template with the value calculated from config\n\tfillTemplate := func(template *api.PodTemplateSpec) error {\n\n\t\t// We will ONLY add config labels with network if we actually\n\t\t// passed in --generate-network-policies to the kompose command\n\t\tif opt.GenerateNetworkPolicies {\n\t\t\ttemplate.ObjectMeta.Labels = transformer.ConfigLabelsWithNetwork(name, service.Network)\n\t\t} else {\n\t\t\ttemplate.ObjectMeta.Labels = transformer.ConfigLabels(name)\n\t\t}\n\t\ttemplate.Spec = podSpec.Get()\n\t\treturn nil\n\t}\n\n\t// fillObjectMeta fills the metadata with the value calculated from config\n\tfillObjectMeta := func(meta *metav1.ObjectMeta) {\n\t\tmeta.Annotations = annotations\n\t}\n\n\t// update supported controller\n\tfor _, obj := range *objects {\n\t\terr := k.UpdateController(obj, fillTemplate, fillObjectMeta)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"k.UpdateController failed\")\n\t\t}\n\t\tif len(service.Volumes) > 0 {\n\t\t\tswitch objType := obj.(type) {\n\t\t\tcase *appsv1.Deployment:\n\t\t\t\tobjType.Spec.Strategy.Type = appsv1.RecreateDeploymentStrategyType\n\t\t\tcase *deployapi.DeploymentConfig:\n\t\t\t\tobjType.Spec.Strategy.Type = deployapi.DeploymentStrategyTypeRecreate\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// UpdateKubernetesObjects loads configurations to k8s objects\nfunc (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions, objects *[]runtime.Object) error {\n\t// Configure the environment variables.\n\tenvs, envsFrom, err := ConfigEnvs(service, opt)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Unable to load env variables\")\n\t}\n\n\t// Configure the container volumes.\n\tvolumesMount, volumes, pvc, cms, err := k.ConfigVolumes(name, service)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"k.ConfigVolumes failed\")\n\t}\n\t// Configure Tmpfs\n\tif len(service.TmpFs) > 0 {\n\t\tTmpVolumesMount, TmpVolumes := k.ConfigTmpfs(name, service)\n\t\tvolumes = append(volumes, TmpVolumes...)\n\t\tvolumesMount = append(volumesMount, TmpVolumesMount...)\n\t}\n\n\tif pvc != nil && opt.Controller != StatefulStateController {\n\t\t// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`\n\t\t// because the type of objects and pvc is different, but when doing append\n\t\t// one element at a time it gets converted to runtime.Object for objects slice\n\t\tfor _, p := range pvc {\n\t\t\t*objects = append(*objects, p)\n\t\t}\n\t}\n\n\tfor _, c := range cms {\n\t\t*objects = append(*objects, c)\n\t}\n\n\t// Configure the container ports.\n\tports := ConfigPorts(service)\n\t// Configure capabilities\n\tcapabilities := ConfigCapabilities(service)\n\n\t// Configure annotations\n\tannotations := transformer.ConfigAnnotations(service)\n\n\t// fillTemplate fills the pod template with the value calculated from config\n\tfillTemplate := func(template *api.PodTemplateSpec) error {\n\t\ttemplate.Spec.Containers[0].Name = GetContainerName(service)\n\t\ttemplate.Spec.Containers[0].Env = envs\n\t\ttemplate.Spec.Containers[0].EnvFrom = envsFrom\n\t\ttemplate.Spec.Containers[0].Command = service.Command\n\t\ttemplate.Spec.Containers[0].Args = GetContainerArgs(service)\n\t\ttemplate.Spec.Containers[0].WorkingDir = service.WorkingDir\n\t\ttemplate.Spec.Containers[0].VolumeMounts = append(template.Spec.Containers[0].VolumeMounts, volumesMount...)\n\t\ttemplate.Spec.Containers[0].Stdin = service.Stdin\n\t\ttemplate.Spec.Containers[0].TTY = service.Tty\n\t\tif opt.Controller != StatefulStateController || opt.Volumes == \"configMap\" {\n\t\t\ttemplate.Spec.Volumes = append(template.Spec.Volumes, volumes...)\n\t\t}\n\t\ttemplate.Spec.Affinity = ConfigAffinity(service)\n\t\ttemplate.Spec.TopologySpreadConstraints = ConfigTopologySpreadConstraints(service)\n\t\t// Configure the HealthCheck\n\t\ttemplate.Spec.Containers[0].LivenessProbe = configProbe(service.HealthChecks.Liveness)\n\t\ttemplate.Spec.Containers[0].ReadinessProbe = configProbe(service.HealthChecks.Readiness)\n\n\t\tif service.StopGracePeriod != \"\" {\n\t\t\ttemplate.Spec.TerminationGracePeriodSeconds, err = DurationStrToSecondsInt(service.StopGracePeriod)\n\t\t\tif err != nil {\n\t\t\t\tlog.Warningf(\"Failed to parse duration \\\"%v\\\" for service \\\"%v\\\"\", service.StopGracePeriod, name)\n\t\t\t}\n\t\t}\n\n\t\tTranslatePodResource(&service, template)\n\n\t\t// Configure resource reservations\n\t\tpodSecurityContext := &api.PodSecurityContext{}\n\n\t\t//set pid namespace mode\n\t\tif service.Pid != \"\" {\n\t\t\tif service.Pid == \"host\" {\n\t\t\t\t// podSecurityContext.HostPID = true\n\t\t\t} else {\n\t\t\t\tlog.Warningf(\"Ignoring PID key for service \\\"%v\\\". Invalid value \\\"%v\\\".\", name, service.Pid)\n\t\t\t}\n\t\t}\n\n\t\t//set supplementalGroups\n\t\tif service.GroupAdd != nil {\n\t\t\tpodSecurityContext.SupplementalGroups = service.GroupAdd\n\t\t}\n\n\t\t//set Security Context FsGroup\n\t\tif service.FsGroup != 0 {\n\t\t\tpodSecurityContext.FSGroup = &service.FsGroup\n\t\t}\n\n\t\t// Setup security context\n\t\tsecurityContext := &api.SecurityContext{}\n\t\tif service.Privileged {\n\t\t\tsecurityContext.Privileged = &service.Privileged\n\t\t}\n\t\tif service.User != \"\" {\n\t\t\tswitch userparts := strings.Split(service.User, \":\"); len(userparts) {\n\t\t\tdefault:\n\t\t\t\tlog.Warn(\"Ignoring ill-formed user directive. Must be in format UID or UID:GID.\")\n\t\t\tcase 1:\n\t\t\t\tuid, err := strconv.ParseInt(userparts[0], 10, 64)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warn(\"Ignoring user directive. User to be specified as a UID (numeric).\")\n\t\t\t\t} else {\n\t\t\t\t\tsecurityContext.RunAsUser = &uid\n\t\t\t\t}\n\t\t\tcase 2:\n\t\t\t\tuid, err := strconv.ParseInt(userparts[0], 10, 64)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warn(\"Ignoring user name in user directive. User to be specified as a UID (numeric).\")\n\t\t\t\t} else {\n\t\t\t\t\tsecurityContext.RunAsUser = &uid\n\t\t\t\t}\n\n\t\t\t\tgid, err := strconv.ParseInt(userparts[1], 10, 64)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warn(\"Ignoring group name in user directive. Group to be specified as a GID (numeric).\")\n\t\t\t\t} else {\n\t\t\t\t\tsecurityContext.RunAsGroup = &gid\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//set capabilities if it is not empty\n\t\tif len(capabilities.Add) > 0 || len(capabilities.Drop) > 0 {\n\t\t\tsecurityContext.Capabilities = capabilities\n\t\t}\n\n\t\t//set readOnlyRootFilesystem if it is enabled\n\t\tif service.ReadOnly {\n\t\t\tsecurityContext.ReadOnlyRootFilesystem = &service.ReadOnly\n\t\t}\n\n\t\t// update template only if securityContext is not empty\n\t\tif *securityContext != (api.SecurityContext{}) {\n\t\t\ttemplate.Spec.Containers[0].SecurityContext = securityContext\n\t\t}\n\t\tif !reflect.DeepEqual(*podSecurityContext, api.PodSecurityContext{}) {\n\t\t\ttemplate.Spec.SecurityContext = podSecurityContext\n\t\t}\n\t\ttemplate.Spec.Containers[0].Ports = ports\n\n\t\t// Only add network mode if generate-network-policies is set\n\t\tif opt.GenerateNetworkPolicies {\n\t\t\ttemplate.ObjectMeta.Labels = transformer.ConfigLabelsWithNetwork(name, service.Network)\n\t\t} else {\n\t\t\ttemplate.ObjectMeta.Labels = transformer.ConfigLabels(name)\n\t\t}\n\n\t\t// Configure the image pull policy\n\t\tpolicy, err := GetImagePullPolicy(name, service.ImagePullPolicy)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttemplate.Spec.Containers[0].ImagePullPolicy = policy\n\n\t\t// Configure the container restart policy.\n\t\trestart, err := GetRestartPolicy(name, service.Restart)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttemplate.Spec.RestartPolicy = restart\n\n\t\t// Configure hostname/domain_name settings\n\t\tif service.HostName != \"\" {\n\t\t\ttemplate.Spec.Hostname = service.HostName\n\t\t}\n\t\tif service.DomainName != \"\" {\n\t\t\ttemplate.Spec.Subdomain = service.DomainName\n\t\t}\n\n\t\tif serviceAccountName, ok := service.Labels[compose.LabelServiceAccountName]; ok {\n\t\t\ttemplate.Spec.ServiceAccountName = serviceAccountName\n\t\t}\n\t\tfillInitContainers(template, service)\n\t\treturn nil\n\t}\n\n\t// fillObjectMeta fills the metadata with the value calculated from config\n\tfillObjectMeta := func(meta *metav1.ObjectMeta) {\n\t\tmeta.Annotations = annotations\n\t}\n\n\t// update supported controller\n\tfor _, obj := range *objects {\n\t\terr = k.UpdateController(obj, fillTemplate, fillObjectMeta)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"k.UpdateController failed\")\n\t\t}\n\t\tif len(service.Volumes) > 0 {\n\t\t\tswitch objType := obj.(type) {\n\t\t\tcase *appsv1.Deployment:\n\t\t\t\tobjType.Spec.Strategy.Type = appsv1.RecreateDeploymentStrategyType\n\t\t\tcase *deployapi.DeploymentConfig:\n\t\t\t\tobjType.Spec.Strategy.Type = deployapi.DeploymentStrategyTypeRecreate\n\t\t\tcase *appsv1.StatefulSet:\n\t\t\t\t// embed all PVCs inside the StatefulSet object\n\t\t\t\tif opt.Volumes == \"configMap\" {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tpersistentVolumeClaims := make([]api.PersistentVolumeClaim, len(pvc))\n\t\t\t\tfor i, persistentVolumeClaim := range pvc {\n\t\t\t\t\tpersistentVolumeClaims[i] = *persistentVolumeClaim\n\t\t\t\t\tpersistentVolumeClaims[i].APIVersion = \"\"\n\t\t\t\t\tpersistentVolumeClaims[i].Kind = \"\"\n\t\t\t\t}\n\t\t\t\tobjType.Spec.VolumeClaimTemplates = persistentVolumeClaims\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// getServiceVolumesID create a unique id for the service's volume mounts\nfunc getServiceVolumesID(service kobject.ServiceConfig) string {\n\tid := \"\"\n\tfor _, v := range service.VolList {\n\t\tid += v\n\t}\n\treturn id\n}\n\n// getServiceGroupID ...\n// return empty string should mean this service should go alone\nfunc getServiceGroupID(service kobject.ServiceConfig, mode string) string {\n\tif mode == \"label\" {\n\t\treturn service.Labels[compose.LabelServiceGroup]\n\t}\n\tif mode == \"volume\" {\n\t\treturn getServiceVolumesID(service)\n\t}\n\treturn \"\"\n}\n\n// KomposeObjectToServiceConfigGroupMapping returns the service config group by name or by volume\n// This group function works as following\n//  1. Support two mode\n//     (1): label: use a custom label, the service that contains it will be merged to one workload.\n//     (2): volume: the service that share to exactly same volume config will be merged to one workload. If use pvc, only\n//     create one for this group.\n//  2. If service containers restart policy and no workload argument provide and it's restart policy looks like a pod, then\n//     this service should generate a pod. If group mode specified, it should be grouped and ignore the restart policy.\n//  3. If group mode specified, port conflict between services in one group will be ignored, and multiple service should be created.\n//  4. If `volume` group mode specified, we don't have an appropriate name for this combined service, use the first one for now.\n//     A warn/info message should be printed to let the user know.\nfunc KomposeObjectToServiceConfigGroupMapping(komposeObject *kobject.KomposeObject, opt kobject.ConvertOptions) map[string]kobject.ServiceConfigGroup {\n\tserviceConfigGroup := make(map[string]kobject.ServiceConfigGroup)\n\tsortedServiceConfigs := SortedKeys(komposeObject.ServiceConfigs)\n\n\tfor _, service := range sortedServiceConfigs {\n\t\tserviceConfig := komposeObject.ServiceConfigs[service]\n\t\tgroupID := getServiceGroupID(serviceConfig, opt.ServiceGroupMode)\n\t\tif groupID != \"\" {\n\t\t\tserviceConfig.Name = service\n\t\t\tserviceConfig.InGroup = true\n\t\t\tserviceConfigGroup[groupID] = append(serviceConfigGroup[groupID], serviceConfig)\n\t\t\tkomposeObject.ServiceConfigs[service] = serviceConfig\n\t\t}\n\t}\n\n\treturn serviceConfigGroup\n}\n\n// TranslatePodResource config pod resources\nfunc TranslatePodResource(service *kobject.ServiceConfig, template *api.PodTemplateSpec) {\n\t// Configure the resource limits\n\tif service.MemLimit != 0 || service.CPULimit != 0 || service.DeployLabels[\"kompose.ephemeral-storage.limit\"] != \"\" {\n\t\tresourceLimit := api.ResourceList{}\n\n\t\tif service.MemLimit != 0 {\n\t\t\tresourceLimit[api.ResourceMemory] = *resource.NewQuantity(int64(service.MemLimit), \"RandomStringForFormat\")\n\t\t}\n\n\t\tif service.CPULimit != 0 {\n\t\t\tresourceLimit[api.ResourceCPU] = *resource.NewMilliQuantity(service.CPULimit, resource.DecimalSI)\n\t\t}\n\n\t\t// Check for ephemeral-storage in deploy labels\n\t\tif val, ok := service.DeployLabels[\"kompose.ephemeral-storage.limit\"]; ok {\n\t\t\tif quantity, err := resource.ParseQuantity(val); err == nil {\n\t\t\t\tresourceLimit[api.ResourceEphemeralStorage] = quantity\n\t\t\t}\n\t\t}\n\n\t\ttemplate.Spec.Containers[0].Resources.Limits = resourceLimit\n\t}\n\n\t// Configure the resource requests\n\tif service.MemReservation != 0 || service.CPUReservation != 0 || service.DeployLabels[\"kompose.ephemeral-storage.request\"] != \"\" {\n\t\tresourceRequests := api.ResourceList{}\n\n\t\tif service.MemReservation != 0 {\n\t\t\tresourceRequests[api.ResourceMemory] = *resource.NewQuantity(int64(service.MemReservation), \"RandomStringForFormat\")\n\t\t}\n\n\t\tif service.CPUReservation != 0 {\n\t\t\tresourceRequests[api.ResourceCPU] = *resource.NewMilliQuantity(service.CPUReservation, resource.DecimalSI)\n\t\t}\n\n\t\t// Check for ephemeral-storage in deploy labels\n\t\tif val, ok := service.DeployLabels[\"kompose.ephemeral-storage.request\"]; ok {\n\t\t\tif quantity, err := resource.ParseQuantity(val); err == nil {\n\t\t\t\tresourceRequests[api.ResourceEphemeralStorage] = quantity\n\t\t\t}\n\t\t}\n\n\t\ttemplate.Spec.Containers[0].Resources.Requests = resourceRequests\n\t}\n}\n\n// GetImagePullPolicy get image pull settings\nfunc GetImagePullPolicy(name, policy string) (api.PullPolicy, error) {\n\tswitch policy {\n\tcase \"\":\n\tcase \"Always\":\n\t\treturn api.PullAlways, nil\n\tcase \"Never\":\n\t\treturn api.PullNever, nil\n\tcase \"IfNotPresent\":\n\t\treturn api.PullIfNotPresent, nil\n\tdefault:\n\t\treturn \"\", errors.New(\"Unknown image-pull-policy \" + policy + \" for service \" + name)\n\t}\n\treturn \"\", nil\n}\n\n// GetRestartPolicy ...\nfunc GetRestartPolicy(name, restart string) (api.RestartPolicy, error) {\n\tswitch restart {\n\tcase \"\", \"always\", \"any\":\n\t\treturn api.RestartPolicyAlways, nil\n\tcase \"no\", \"none\":\n\t\treturn api.RestartPolicyNever, nil\n\tcase \"on-failure\":\n\t\treturn api.RestartPolicyOnFailure, nil\n\tdefault:\n\t\treturn \"\", errors.New(\"Unknown restart policy \" + restart + \" for service \" + name)\n\t}\n}\n\n// SortServicesFirst - the objects that we get can be in any order this keeps services first\n// according to best practice kubernetes services should be created first\n// http://kubernetes.io/docs/user-guide/config-best-practices/\nfunc (k *Kubernetes) SortServicesFirst(objs *[]runtime.Object) {\n\tvar svc, others, ret []runtime.Object\n\n\tfor _, obj := range *objs {\n\t\tif obj.GetObjectKind().GroupVersionKind().Kind == \"Service\" {\n\t\t\tsvc = append(svc, obj)\n\t\t} else {\n\t\t\tothers = append(others, obj)\n\t\t}\n\t}\n\tret = append(ret, svc...)\n\tret = append(ret, others...)\n\t*objs = ret\n}\n\n// RemoveDupObjects remove objects that are dups...eg. configmaps from env.\n// since we know for sure that the duplication can only happen on ConfigMap, so\n// this code will looks like this for now.\n// + NetworkPolicy\nfunc (k *Kubernetes) RemoveDupObjects(objs *[]runtime.Object) {\n\tvar result []runtime.Object\n\texist := map[string]bool{}\n\tfor _, obj := range *objs {\n\t\tif us, ok := obj.(metav1.Object); ok {\n\t\t\tk := obj.GetObjectKind().GroupVersionKind().String() + us.GetNamespace() + us.GetName()\n\t\t\tif exist[k] {\n\t\t\t\tlog.Debugf(\"Remove duplicate resource: %s/%s\", obj.GetObjectKind().GroupVersionKind().Kind, us.GetName())\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tresult = append(result, obj)\n\t\t\t\texist[k] = true\n\t\t\t}\n\t\t} else {\n\t\t\tresult = append(result, obj)\n\t\t}\n\t}\n\t*objs = result\n}\n\n// SortedKeys Ensure the kubernetes objects are in a consistent order\nfunc SortedKeys[V kobject.ServiceConfig | kobject.ServiceConfigGroup](serviceConfig map[string]V) []string {\n\tvar sortedKeys []string\n\tfor name := range serviceConfig {\n\t\tsortedKeys = append(sortedKeys, name)\n\t}\n\tsort.Strings(sortedKeys)\n\treturn sortedKeys\n}\n\n// DurationStrToSecondsInt converts duration string to *int64 in seconds\nfunc DurationStrToSecondsInt(s string) (*int64, error) {\n\tif s == \"\" {\n\t\treturn nil, nil\n\t}\n\tduration, err := time.ParseDuration(s)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tr := (int64)(duration.Seconds())\n\treturn &r, nil\n}\n\n// GetEnvsFromFile get env vars from env_file\nfunc GetEnvsFromFile(file string) (map[string]string, error) {\n\n\tenvLoad, err := godotenv.Read(file)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Unable to read env_file\")\n\t}\n\n\treturn envLoad, nil\n}\n\nfunc LoadEnvFiles(file string, lookup func(key string) (string, bool)) (map[string]string, error) {\n\treturn dotenv.ReadWithLookup(lookup, file)\n}\n\n// GetContentFromFile gets the content from the file..\nfunc GetContentFromFile(file string) (string, error) {\n\tfileBytes, err := os.ReadFile(file)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"Unable to read file\")\n\t}\n\treturn string(fileBytes), nil\n}\n\n// FormatEnvName format env name\nfunc FormatEnvName(name string, serviceName string) string {\n\tenvName := strings.Trim(name, \"./\")\n\n\t// replace all non-alphanumerical characters with dashes to have a unique envName (env filename could be used multiple times)\n\tenvName = regexp.MustCompile(`[^a-zA-Z0-9]`).ReplaceAllString(envName, \"-\")\n\tenvName = getUsableNameEnvFile(envName, serviceName)\n\treturn envName\n}\n\n// getUsableNameEnvFile checks and adjusts the environment file name to make it usable.\n// If the first character of envName is a hyphen \"-\", it is concatenated with nameService.\n// If the length of envName is greater than 63, it is truncated to 63 characters.\n// Returns the adjusted environment file name.\nfunc getUsableNameEnvFile(envName string, serviceName string) string {\n\tif string(envName[0]) == \"-\" { // -env-local....\n\t\tenvName = fmt.Sprintf(\"%s%s\", serviceName, envName)\n\t}\n\tif len(envName) > 63 {\n\t\tenvName = envName[0:63]\n\t}\n\treturn envName\n}\n\n// FormatFileName format file name\nfunc FormatFileName(name string) string {\n\t// Split the filepath name so that we use the\n\t// file name (after the base) for ConfigMap,\n\t// it shouldn't matter whether it has special characters or not\n\t_, file := path.Split(name)\n\n\t// Make it DNS-1123 compliant for Kubernetes\n\treturn strings.Replace(file, \"_\", \"-\", -1)\n}\n\n// FormatContainerName format Container name\nfunc FormatContainerName(name string) string {\n\tname = strings.Replace(name, \"_\", \"-\", -1)\n\treturn name\n}\n\n// GetContainerName returns the name of the container, from the service config object\nfunc GetContainerName(service kobject.ServiceConfig) string {\n\tname := service.Name\n\tif len(service.ContainerName) > 0 {\n\t\tname = service.ContainerName\n\t}\n\treturn FormatContainerName(name)\n}\n\n// FormatResourceName generate a valid k8s resource name\nfunc FormatResourceName(name string) string {\n\treturn strings.ToLower(strings.Replace(name, \"_\", \"-\", -1))\n}\n\n// GetContainerArgs update the interpolation of env variables if exists.\n// example: [curl, $PROTOCOL://$DOMAIN] => [curl, $(PROTOCOL)://$(DOMAIN)]\nfunc GetContainerArgs(service kobject.ServiceConfig) []string {\n\tvar args []string\n\tre := regexp.MustCompile(`\\$([a-zA-Z0-9]*)`)\n\tfor _, arg := range service.Args {\n\t\targ = re.ReplaceAllString(arg, `$($1)`)\n\t\targs = append(args, arg)\n\t}\n\treturn args\n}\n\n// GetFileName extracts the file name from a given file path or file name.\n// If the input fileName contains a \"/\", it retrieves the substring after the last \"/\".\n// The function does not format the file name further, as it may contain periods or other valid characters.\n// Returns the extracted file name.\nfunc GetFileName(fileName string) string {\n\treturn filepath.Base(fileName)\n}\n\n// reformatSecretConfigUnderscoreWithDash takes a ServiceSecretConfig object as input and returns a new instance of ServiceSecretConfig\n// where the values of Source and Target are formatted using the FormatResourceName function to replace underscores with dashes and lowercase,\n// while the other fields remain unchanged. This is done to ensure consistency in the format of container names within the service's secret configuration.\n// this function ensures that source, target names are in an acceptable format for Kubernetes and other systems that may require a specific naming format.\nfunc reformatSecretConfigUnderscoreWithDash(secretConfig types.ServiceSecretConfig) types.ServiceSecretConfig {\n\tnewSecretConfig := types.ServiceSecretConfig{\n\t\tSource:     FormatResourceName(secretConfig.Source),\n\t\tTarget:     FormatResourceName(secretConfig.Target),\n\t\tUID:        secretConfig.UID,\n\t\tGID:        secretConfig.GID,\n\t\tMode:       secretConfig.Mode,\n\t\tExtensions: secretConfig.Extensions,\n\t}\n\n\treturn newSecretConfig\n}\n\n// fillInitContainers looks for an initContainer resources and its passed as labels\n// if there is no image, it does not fill the initContainer\n// https://kubernetes.io/docs/concepts/workloads/pods/init-containers/\nfunc fillInitContainers(template *api.PodTemplateSpec, service kobject.ServiceConfig) {\n\tresourceImage, exist := service.Labels[compose.LabelInitContainerImage]\n\tif !exist || resourceImage == \"\" {\n\t\treturn\n\t}\n\tresourceName, exist := service.Labels[compose.LabelInitContainerName]\n\tif !exist || resourceName == \"\" {\n\t\tresourceName = \"init-service\"\n\t}\n\n\ttemplate.Spec.InitContainers = append(template.Spec.InitContainers, api.Container{\n\t\tName:    resourceName,\n\t\tCommand: parseContainerCommandsFromStr(service.Labels[compose.LabelInitContainerCommand]),\n\t\tImage:   resourceImage,\n\t})\n}\n\n// parseContainerCommandsFromStr parses a string containing comma-separated commands\n// returns a slice of strings or a single command\n// example:\n// [ \"bundle\", \"exec\", \"thin\", \"-p\", \"3000\" ]\n//\n// example:\n// [ \"bundle exec thin -p 3000\" ]\nfunc parseContainerCommandsFromStr(line string) []string {\n\tif line == \"\" {\n\t\treturn []string{}\n\t}\n\tvar commands []string\n\tif strings.Contains(line, \",\") {\n\t\tline = strings.TrimSpace(strings.Trim(line, \"[]\"))\n\t\tcommands = strings.Split(line, \",\")\n\t\t// remove space \"'\n\t\tfor i := range commands {\n\t\t\tcommands[i] = strings.TrimSpace(strings.Trim(commands[i], `\"' `))\n\t\t}\n\t} else {\n\t\tcommands = append(commands, line)\n\t}\n\treturn commands\n}\n\n// searchHPAValues is useful to check if labels\n// contains any labels related to Horizontal Pod Autoscaler\nfunc searchHPAValues(labels map[string]string) bool {\n\tfor _, value := range LabelKeys {\n\t\tif _, ok := labels[value]; ok {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// createHPAResources creates a HorizontalPodAutoscaler (HPA) resource\n// It sets the number of replicas in the service to 0 because\n// the number of replicas will be managed by the HPA\nfunc createHPAResources(name string, service *kobject.ServiceConfig) hpa.HorizontalPodAutoscaler {\n\tvaluesHpa := getResourceHpaValues(service)\n\tservice.Replicas = 0\n\tmetrics := getHpaMetricSpec(valuesHpa)\n\tscalerSpecs := hpa.HorizontalPodAutoscaler{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: name,\n\t\t},\n\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\tKind:       \"Deployment\",\n\t\t\t\tName:       name,\n\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t},\n\t\t\tMinReplicas: &valuesHpa.MinReplicas,\n\t\t\tMaxReplicas: valuesHpa.MaxReplicas,\n\t\t\tMetrics:     metrics,\n\t\t},\n\t}\n\n\treturn scalerSpecs\n}\n\n// getResourceHpaValues retrieves the min/max replicas and CPU/memory utilization values\n// control if maxReplicas is less than minReplicas\nfunc getResourceHpaValues(service *kobject.ServiceConfig) HpaValues {\n\tminReplicas := getHpaValue(service, compose.LabelHpaMinReplicas, DefaultMinReplicas)\n\tmaxReplicas := getHpaValue(service, compose.LabelHpaMaxReplicas, DefaultMaxReplicas)\n\n\tif maxReplicas < minReplicas {\n\t\tlog.Warnf(\"maxReplicas %d is less than minReplicas %d. Using minReplicas value %d\", maxReplicas, minReplicas, minReplicas)\n\t\tmaxReplicas = minReplicas\n\t}\n\n\tcpuUtilization := validatePercentageMetric(service, compose.LabelHpaCPU, DefaultCPUUtilization)\n\tmemoryUtilization := validatePercentageMetric(service, compose.LabelHpaMemory, DefaultMemoryUtilization)\n\n\treturn HpaValues{\n\t\tMinReplicas:       minReplicas,\n\t\tMaxReplicas:       maxReplicas,\n\t\tCPUtilization:     cpuUtilization,\n\t\tMemoryUtilization: memoryUtilization,\n\t}\n}\n\n// validatePercentageMetric validates the CPU or memory metrics value\n// ensuring that it falls within the acceptable range [1, 100].\nfunc validatePercentageMetric(service *kobject.ServiceConfig, metricLabel string, defaultValue int32) int32 {\n\tmetricValue := getHpaValue(service, metricLabel, defaultValue)\n\tif metricValue > 100 || metricValue < 1 {\n\t\tlog.Warnf(\"Metric value %d is not within the acceptable range [1, 100]. Using default value %d\", metricValue, defaultValue)\n\t\treturn defaultValue\n\t}\n\treturn metricValue\n}\n\n// getHpaValue convert the label value to integer\n// If the label is not present or the conversion fails\n// it returns the provided default value\nfunc getHpaValue(service *kobject.ServiceConfig, label string, defaultValue int32) int32 {\n\tvalueFromLabel, err := strconv.Atoi(service.Labels[label])\n\tif err != nil || valueFromLabel < 0 {\n\t\tlog.Warnf(\"Error converting label %s. Using default value %d\", label, defaultValue)\n\t\treturn defaultValue\n\t}\n\treturn int32(valueFromLabel)\n}\n\n// getHpaMetricSpec returns a list of metric specs for the HPA resource\n// Target type is hardcoded to hpa.UtilizationMetricType\n// Each MetricSpec specifies the type metric CPU/memory and average utilization value\n// to trigger scaling\nfunc getHpaMetricSpec(hpaValues HpaValues) []hpa.MetricSpec {\n\tvar metrics []hpa.MetricSpec\n\tif hpaValues.CPUtilization > 0 {\n\t\tmetrics = append(metrics, hpa.MetricSpec{\n\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\tName: api.ResourceCPU,\n\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\tAverageUtilization: &hpaValues.CPUtilization,\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t}\n\tif hpaValues.MemoryUtilization > 0 {\n\t\tmetrics = append(metrics, hpa.MetricSpec{\n\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\tName: api.ResourceMemory,\n\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\tAverageUtilization: &hpaValues.MemoryUtilization,\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t}\n\treturn metrics\n}\n\n// isConfigFile checks if the given filePath should be used as a configMap\n// if dir is not empty, withindir are treated as cofigmaps\n// if it's configMap, mount readonly as default\nfunc isConfigFile(filePath string) (useConfigMap bool, readonly bool, skip bool) {\n\tif filePath == \"\" || strings.HasSuffix(filePath, \".sock\") {\n\t\tskip = true\n\t\treturn\n\t}\n\n\tfi, err := os.Stat(filePath)\n\tif err != nil {\n\t\tlog.Warnf(\"File don't exist or failed to check if the directory is empty: %v\", err)\n\t\t// dir/file not exist\n\t\t// here not assigned skip to true,\n\t\t// maybe dont want to skip\n\t\treturn\n\t}\n\n\tif !fi.Mode().IsRegular() { // is dir\n\t\tisDirEmpty, err := checkIsEmptyDir(filePath)\n\t\tif err != nil {\n\t\t\tlog.Warnf(\"Failed to check if the directory is empty: %v\", err)\n\t\t\tskip = true\n\t\t\treturn\n\t\t}\n\n\t\tif isDirEmpty {\n\t\t\treturn\n\t\t}\n\t}\n\treturn true, true, skip\n}\n\n// checkIsEmptyDir checks if filepath is empty\nfunc checkIsEmptyDir(filePath string) (bool, error) {\n\tfiles, err := os.ReadDir(filePath)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tif len(files) == 0 {\n\t\treturn true, err\n\t}\n\tfor _, file := range files {\n\t\tif !file.IsDir() {\n\t\t\treturn false, nil\n\t\t}\n\t\t_, err := checkIsEmptyDir(file.Name())\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t}\n\treturn true, nil\n}\n\n// setVolumeAccessMode sets the access mode for a volume based on the mode string\n// current types:\n// ReadOnly RO and ReadOnlyMany ROX can be mounted in read-only mode to many hosts\n// ReadWriteMany RWX can be mounted in read/write mode to many hosts\n// ReadWriteOncePod RWOP can be mounted in read/write mode to exactly 1 pod\n// ReadWriteOnce RWO can be mounted in read/write mode to exactly 1 host\n// https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes\nfunc setVolumeAccessMode(mode string, volumeAccesMode []api.PersistentVolumeAccessMode) []api.PersistentVolumeAccessMode {\n\tswitch mode {\n\tcase \"ro\", \"rox\":\n\t\tvolumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadOnlyMany}\n\tcase \"rwx\":\n\t\tvolumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteMany}\n\tcase \"rwop\":\n\t\tvolumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteOncePod}\n\tcase \"rwo\":\n\t\tvolumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteOnce}\n\tdefault:\n\t\tvolumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteOnce}\n\t}\n\n\treturn volumeAccesMode\n}\n\n// fixNetworkModeToService is responsible for adjusting the network mode of services in docker compose (services:)\n// generate a mapping of deployments based on the network mode of each service\n// merging containers into the destination deployment, and removing transferred deployments\nfunc (k *Kubernetes) fixNetworkModeToService(objects *[]runtime.Object, services map[string]kobject.ServiceConfig) {\n\tdeploymentMappings := searchNetworkModeToService(services)\n\tif len(deploymentMappings) == 0 {\n\t\treturn\n\t}\n\tmergeContainersIntoDestinationDeployment(deploymentMappings, objects)\n\tremoveDeploymentTransfered(deploymentMappings, objects)\n}\n\n// mergeContainersIntoDestinationDeployment takes a list of deployment mappings and a list of runtime objects\n// and merges containers from source deployment into the destination deployment\nfunc mergeContainersIntoDestinationDeployment(deploymentMappings []DeploymentMapping, objects *[]runtime.Object) {\n\tfor _, currentDeploymentMap := range deploymentMappings {\n\t\taddContainersFromSourceToTargetDeployment(objects, currentDeploymentMap)\n\t}\n}\n\n// addContainersFromSourceToTargetDeployment adds containers from the source deployment\n// if current deployment name matches source deployment name\nfunc addContainersFromSourceToTargetDeployment(objects *[]runtime.Object, currentDeploymentMap DeploymentMapping) {\n\tfor _, obj := range *objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tif deploy.ObjectMeta.Name == currentDeploymentMap.SourceDeploymentName {\n\t\t\t\taddContainersToTargetDeployment(objects, deploy.Spec.Template.Spec.Containers, currentDeploymentMap.TargetDeploymentName)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// addContainersToTargetDeployment takes\n// - list of runtime objects\n// - list of containers to append\n// - deployment name to transfer\n// appends the containers to the target deployment if its name matches\nfunc addContainersToTargetDeployment(objects *[]runtime.Object, containersToAppend []api.Container, nameDeploymentToTransfer string) {\n\tfor _, obj := range *objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tif deploy.ObjectMeta.Name == nameDeploymentToTransfer {\n\t\t\t\tdeploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, containersToAppend...)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// searchNetworkModeToService iterates over services and checking their network mode service:\n// its separates over process of transferring containers,\n// it determines where each container should be removed from and where it should be added to\nfunc searchNetworkModeToService(services map[string]kobject.ServiceConfig) (deploymentMappings []DeploymentMapping) {\n\tdeploymentMappings = []DeploymentMapping{}\n\tfor _, service := range services {\n\t\tif !strings.Contains(service.NetworkMode, NetworkModeService) {\n\t\t\tcontinue\n\t\t}\n\t\tsplitted := strings.Split(service.NetworkMode, \":\")\n\t\tif len(splitted) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\tdeploymentMappings = append(deploymentMappings, DeploymentMapping{\n\t\t\tSourceDeploymentName: service.Name,\n\t\t\tTargetDeploymentName: splitted[1],\n\t\t})\n\t}\n\treturn deploymentMappings\n}\n\n// removeDeploymentTransfered iterates over a list of DeploymentMapping and\n// removes each deployment that marked in deploymentMappings\nfunc removeDeploymentTransfered(deploymentMappings []DeploymentMapping, objects *[]runtime.Object) {\n\tfor _, currentDeploymentMap := range deploymentMappings {\n\t\tremoveTargetDeployment(objects, currentDeploymentMap.SourceDeploymentName)\n\t}\n}\n\n// removeTargetDeployment iterates over a list of runtime objects\n// and removes the target deployment from the list\nfunc removeTargetDeployment(objects *[]runtime.Object, targetDeploymentName string) {\n\tfor i := len(*objects) - 1; i >= 0; i-- {\n\t\tif deploy, ok := (*objects)[i].(*appsv1.Deployment); ok {\n\t\t\tif deploy.ObjectMeta.Name == targetDeploymentName {\n\t\t\t\t*objects = removeFromSlice(*objects, (*objects)[i])\n\t\t\t}\n\t\t}\n\t}\n}\n\n// removeFromSlice removes a specific object from a slice of runtime objects and returns the updated slice\nfunc removeFromSlice(objects []runtime.Object, objectToRemove runtime.Object) []runtime.Object {\n\tfor i, currentObject := range objects {\n\t\tif reflect.DeepEqual(currentObject, objectToRemove) {\n\t\t\treturn append(objects[:i], objects[i+1:]...)\n\t\t}\n\t}\n\treturn objects\n}\n"
  },
  {
    "path": "pkg/transformer/kubernetes/k8sutils_test.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage kubernetes\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/loader/compose\"\n\t\"github.com/kubernetes/kompose/pkg/testutils\"\n\t\"github.com/pkg/errors\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\thpa \"k8s.io/api/autoscaling/v2beta2\"\n\tapi \"k8s.io/api/core/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/resource\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\n/*\nTest the creation of a service\n*/\nfunc TestCreateService(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"}, // not supported\n\t\tLabels:        nil,\n\t\tAnnotations:   map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:      1,                    // not supported\n\t\tCapAdd:        []string{\"cap_add\"},  // not supported\n\t\tCapDrop:       []string{\"cap_drop\"}, // not supported\n\t\tExpose:        []string{\"expose\"},   // not supported\n\t\tPrivileged:    true,\n\t\tRestart:       \"always\",\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\t_, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t// Test the creation of the service\n\tsvc := k.CreateService(\"foo\", service)\n\n\tif svc.Spec.Ports[0].Port != 123 {\n\t\tt.Errorf(\"Expected port 123 upon conversion, actual %d\", svc.Spec.Ports[0].Port)\n\t}\n}\n\n/*\nTest the creation of a service with a memory limit and reservation\n*/\nfunc TestCreateServiceWithMemLimit(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName:  \"name\",\n\t\tImage:          \"image\",\n\t\tEnvironment:    []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:           []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:        []string{\"cmd\"},\n\t\tWorkingDir:     \"dir\",\n\t\tArgs:           []string{\"arg1\", \"arg2\"},\n\t\tVolList:        []string{\"/tmp/volume\"},\n\t\tNetwork:        []string{\"network1\", \"network2\"}, // not supported\n\t\tLabels:         nil,\n\t\tAnnotations:    map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:       1,                    // not supported\n\t\tCapAdd:         []string{\"cap_add\"},  // not supported\n\t\tCapDrop:        []string{\"cap_drop\"}, // not supported\n\t\tExpose:         []string{\"expose\"},   // not supported\n\t\tPrivileged:     true,\n\t\tRestart:        \"always\",\n\t\tMemLimit:       1337,\n\t\tMemReservation: 1338,\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t// Retrieve the deployment object and test that it matches the mem value\n\tfor _, obj := range objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tmemLimit, _ := deploy.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().AsInt64()\n\t\t\tif memLimit != 1337 {\n\t\t\t\tt.Errorf(\"Expected 1337 for memory limit check, got %v\", memLimit)\n\t\t\t}\n\t\t\tmemReservation, _ := deploy.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().AsInt64()\n\t\t\tif memReservation != 1338 {\n\t\t\t\tt.Errorf(\"Expected 1338 for memory reservation check, got %v\", memReservation)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\nTest the creation of a service with a cpu limit and reservation\n*/\nfunc TestCreateServiceWithCPULimit(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName:  \"name\",\n\t\tImage:          \"image\",\n\t\tEnvironment:    []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:           []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:        []string{\"cmd\"},\n\t\tWorkingDir:     \"dir\",\n\t\tArgs:           []string{\"arg1\", \"arg2\"},\n\t\tVolList:        []string{\"/tmp/volume\"},\n\t\tNetwork:        []string{\"network1\", \"network2\"}, // not supported\n\t\tLabels:         nil,\n\t\tAnnotations:    map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:       1,                    // not supported\n\t\tCapAdd:         []string{\"cap_add\"},  // not supported\n\t\tCapDrop:        []string{\"cap_drop\"}, // not supported\n\t\tExpose:         []string{\"expose\"},   // not supported\n\t\tPrivileged:     true,\n\t\tRestart:        \"always\",\n\t\tCPULimit:       10,\n\t\tCPUReservation: 1,\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t// Retrieve the deployment object and test that it matches the cpu value\n\tfor _, obj := range objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tcpuLimit := deploy.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().MilliValue()\n\t\t\tif cpuLimit != 10 {\n\t\t\t\tt.Errorf(\"Expected 10 for cpu limit check, got %v\", cpuLimit)\n\t\t\t}\n\t\t\tcpuReservation := deploy.Spec.Template.Spec.Containers[0].Resources.Requests.Cpu().MilliValue()\n\t\t\tif cpuReservation != 1 {\n\t\t\t\tt.Errorf(\"Expected 1 for cpu reservation check, got %v\", cpuReservation)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\nTest the creation of a service with ephemeral storage limit\n*/\nfunc TestDeployLabelsEphemeralStorageLimit(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"},\n\t\tLabels:        nil,\n\t\tAnnotations:   map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:      1,\n\t\tCapAdd:        []string{\"cap_add\"},\n\t\tCapDrop:       []string{\"cap_drop\"},\n\t\tExpose:        []string{\"expose\"},\n\t\tPrivileged:    true,\n\t\tRestart:       \"always\",\n\t\tDeployLabels:  map[string]string{\"kompose.ephemeral-storage.limit\": \"1Gi\"},\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t// Retrieve the deployment object and test that it matches the ephemeral storage limit value\n\tfor _, obj := range objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tstorageLimit := deploy.Spec.Template.Spec.Containers[0].Resources.Limits.StorageEphemeral()\n\t\t\texpectedLimit := resource.MustParse(\"1Gi\")\n\t\t\tif *storageLimit != expectedLimit {\n\t\t\t\tt.Errorf(\"Expected %v for ephemeral storage limit check, got %v\", expectedLimit, storageLimit)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\nTest the creation of a service with ephemeral storage request\n*/\nfunc TestDeployLabelsEphemeralStorageRequest(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"},\n\t\tLabels:        nil,\n\t\tAnnotations:   map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:      1,\n\t\tCapAdd:        []string{\"cap_add\"},\n\t\tCapDrop:       []string{\"cap_drop\"},\n\t\tExpose:        []string{\"expose\"},\n\t\tPrivileged:    true,\n\t\tRestart:       \"always\",\n\t\tDeployLabels:  map[string]string{\"kompose.ephemeral-storage.request\": \"1Gi\"},\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t// Retrieve the deployment object and test that it matches the ephemeral storage request value\n\tfor _, obj := range objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tstorageRequest := deploy.Spec.Template.Spec.Containers[0].Resources.Requests.StorageEphemeral()\n\t\t\texpectedRequest := resource.MustParse(\"1Gi\")\n\t\t\tif *storageRequest != expectedRequest {\n\t\t\t\tt.Errorf(\"Expected %v for ephemeral storage request check, got %v\", expectedRequest, storageRequest)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\nTest the creation of a service with a specified user.\nThe expected result is that Kompose will set user in PodSpec\n*/\nfunc TestCreateServiceWithServiceUser(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"}, // not supported\n\t\tLabels:        nil,\n\t\tAnnotations:   map[string]string{\"kompose.service.type\": \"nodeport\"},\n\t\tCPUQuota:      1,                    // not supported\n\t\tCapAdd:        []string{\"cap_add\"},  // not supported\n\t\tCapDrop:       []string{\"cap_drop\"}, // not supported\n\t\tExpose:        []string{\"expose\"},   // not supported\n\t\tPrivileged:    true,\n\t\tRestart:       \"always\",\n\t\tUser:          \"1234:5678\",\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\tfor _, obj := range objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tuid := *deploy.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser\n\t\t\tgid := *deploy.Spec.Template.Spec.Containers[0].SecurityContext.RunAsGroup\n\t\t\tif fmt.Sprintf(\"%d:%d\", uid, gid) != service.User {\n\t\t\t\tt.Errorf(\"User and group in ServiceConfig is not matching user in PodSpec\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCreateServiceWithConfigLongSyntax(t *testing.T) {\n\tcontent := \"setting: true\"\n\ttarget := \"/etc/config.yaml\"\n\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName:   \"name\",\n\t\tImage:           \"image\",\n\t\tEnvironment:     []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:            []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:         []string{\"cmd\"},\n\t\tConfigs:         []types.ServiceConfigObjConfig{{Source: \"configmap\", Target: target}},\n\t\tConfigsMetaData: map[string]types.ConfigObjConfig{\"configmap\": {Content: content}},\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\n\t\t\t\"app\": service,\n\t\t},\n\t}\n\n\tk := Kubernetes{}\n\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\tfor _, obj := range objects {\n\t\tt.Log(obj)\n\t\tif configMap, ok := obj.(*api.ConfigMap); ok {\n\t\t\tfileContent := configMap.Data[\"config.yaml\"]\n\t\t\tif fileContent != content {\n\t\t\t\tt.Errorf(\"Config map content not equal\")\n\t\t\t}\n\t\t}\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tspec := deployment.Spec.Template.Spec\n\t\t\tif spec.Containers[0].VolumeMounts[0].MountPath != target {\n\t\t\t\tt.Errorf(\"Config map mountPath not found\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCreateServiceWithConfigShortSyntax(t *testing.T) {\n\tcontent := \"setting: true\"\n\tsource := \"configmap\"\n\ttarget := \"/\" + source\n\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName:   \"name\",\n\t\tImage:           \"image\",\n\t\tEnvironment:     []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:            []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:         []string{\"cmd\"},\n\t\tConfigs:         []types.ServiceConfigObjConfig{{Source: source}},\n\t\tConfigsMetaData: map[string]types.ConfigObjConfig{source: {Content: content}},\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\n\t\t\t\"app\": service,\n\t\t},\n\t}\n\n\tk := Kubernetes{}\n\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\tfor _, obj := range objects {\n\t\tt.Log(obj)\n\t\tif configMap, ok := obj.(*api.ConfigMap); ok {\n\t\t\tfileContent := configMap.Data[source]\n\t\t\tif fileContent != content {\n\t\t\t\tt.Errorf(\"Config map content not equal\")\n\t\t\t}\n\t\t}\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tspec := deployment.Spec.Template.Spec\n\t\t\tif spec.Containers[0].VolumeMounts[0].MountPath != target {\n\t\t\t\tt.Errorf(\"Config map mountPath not found\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestTransformWithPid(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"},\n\t\tRestart:       \"always\",\n\t\tPid:           \"host\",\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\t_, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t//for _, obj := range objects {\n\t//\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t//\t\thostPid := deploy.Spec.Template.Spec.SecurityContext.HostPID\n\t//\t\tif !hostPid {\n\t//\t\t\tt.Errorf(\"Pid in ServiceConfig is not matching HostPID in PodSpec\")\n\t//\t\t}\n\t//\t}\n\t//}\n}\n\nfunc TestTransformWithInvalidPid(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"},\n\t\tRestart:       \"always\",\n\t\tPid:           \"badvalue\",\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\t_, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\t//for _, obj := range objects {\n\t//\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t//\t\tif deploy.Spec.Template.Spec.SecurityContext != nil {\n\t//\t\t\thostPid := deploy.Spec.Template.Spec.SecurityContext.HostPID\n\t//\t\t\tif hostPid {\n\t//\t\t\t\tt.Errorf(\"Pid in ServiceConfig is not matching HostPID in PodSpec\")\n\t//\t\t\t}\n\t//\t\t}\n\t//\t}\n\t//}\n}\n\nfunc TestIsDir(t *testing.T) {\n\ttempPath := \"/tmp/kompose_unit\"\n\ttempDir := filepath.Join(tempPath, \"i_am_dir\")\n\ttempFile := filepath.Join(tempPath, \"i_am_file\")\n\ttempAbsentDirPath := filepath.Join(tempPath, \"i_do_not_exist\")\n\n\t// create directory\n\terr := os.MkdirAll(tempDir, 0744)\n\tif err != nil {\n\t\tt.Errorf(\"Unable to create directory: %v\", err)\n\t}\n\n\t// create empty file\n\tf, err := os.Create(tempFile)\n\tif err != nil {\n\t\tt.Errorf(\"Unable to create empty file: %v\", err)\n\t}\n\tf.Close()\n\n\t// Check output if directory exists\n\toutput, err := isDir(tempDir)\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"isDir failed\"))\n\t}\n\tif !output {\n\t\tt.Errorf(\"directory %v exists but isDir() returned %v\", tempDir, output)\n\t}\n\n\t// Check output if file is provided\n\toutput, err = isDir(tempFile)\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"isDir failed\"))\n\t}\n\tif output {\n\t\tt.Errorf(\"%v is a file but isDir() returned %v\", tempDir, output)\n\t}\n\n\t// Check output if path does not exist\n\toutput, err = isDir(tempAbsentDirPath)\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"isDir failed\"))\n\t}\n\tif output {\n\t\tt.Errorf(\"Directory %v does not exist, but isDir() returned %v\", tempAbsentDirPath, output)\n\t}\n\n\t// delete temporary directory\n\terr = os.RemoveAll(tempPath)\n\tif err != nil {\n\t\tt.Errorf(\"Error removing the temporary directory during cleanup: %v\", err)\n\t}\n}\n\n// TestServiceWithHealthCheck this tests if Headless Service is created for services with HealthCheck.\nfunc TestServiceWithHealthCheck(t *testing.T) {\n\ttestCases := map[string]struct {\n\t\tservice kobject.ServiceConfig\n\t}{\n\t\t\"Exec\": {\n\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\tContainerName: \"name\",\n\t\t\t\tImage:         \"image\",\n\t\t\t\tServiceType:   \"Headless\",\n\t\t\t\tHealthChecks: kobject.HealthChecks{\n\t\t\t\t\tReadiness: kobject.HealthCheck{\n\t\t\t\t\t\tTest:        []string{\"arg1\", \"arg2\"},\n\t\t\t\t\t\tTimeout:     10,\n\t\t\t\t\t\tInterval:    5,\n\t\t\t\t\t\tRetries:     3,\n\t\t\t\t\t\tStartPeriod: 60,\n\t\t\t\t\t},\n\t\t\t\t\tLiveness: kobject.HealthCheck{\n\t\t\t\t\t\tTest:        []string{\"arg1\", \"arg2\"},\n\t\t\t\t\t\tTimeout:     11,\n\t\t\t\t\t\tInterval:    6,\n\t\t\t\t\t\tRetries:     4,\n\t\t\t\t\t\tStartPeriod: 61,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"HTTPGet\": {\n\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\tContainerName: \"name\",\n\t\t\t\tImage:         \"image\",\n\t\t\t\tServiceType:   \"Headless\",\n\t\t\t\tHealthChecks: kobject.HealthChecks{\n\t\t\t\t\tReadiness: kobject.HealthCheck{\n\t\t\t\t\t\tHTTPPath:    \"/health\",\n\t\t\t\t\t\tHTTPPort:    8080,\n\t\t\t\t\t\tTimeout:     10,\n\t\t\t\t\t\tInterval:    5,\n\t\t\t\t\t\tRetries:     3,\n\t\t\t\t\t\tStartPeriod: 60,\n\t\t\t\t\t},\n\t\t\t\t\tLiveness: kobject.HealthCheck{\n\t\t\t\t\t\tHTTPPath:    \"/ready\",\n\t\t\t\t\t\tHTTPPort:    8080,\n\t\t\t\t\t\tTimeout:     11,\n\t\t\t\t\t\tInterval:    6,\n\t\t\t\t\t\tRetries:     4,\n\t\t\t\t\t\tStartPeriod: 61,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"TCPSocket\": {\n\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\tContainerName: \"name\",\n\t\t\t\tImage:         \"image\",\n\t\t\t\tServiceType:   \"Headless\",\n\t\t\t\tHealthChecks: kobject.HealthChecks{\n\t\t\t\t\tReadiness: kobject.HealthCheck{\n\t\t\t\t\t\tTCPPort:     8080,\n\t\t\t\t\t\tTimeout:     10,\n\t\t\t\t\t\tInterval:    5,\n\t\t\t\t\t\tRetries:     3,\n\t\t\t\t\t\tStartPeriod: 60,\n\t\t\t\t\t},\n\t\t\t\t\tLiveness: kobject.HealthCheck{\n\t\t\t\t\t\tTCPPort:     8080,\n\t\t\t\t\t\tTimeout:     11,\n\t\t\t\t\t\tInterval:    6,\n\t\t\t\t\t\tRetries:     4,\n\t\t\t\t\t\tStartPeriod: 61,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, testCase := range testCases {\n\t\tk := Kubernetes{}\n\t\tkomposeObject := kobject.KomposeObject{\n\t\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": testCase.service},\n\t\t}\n\t\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\t\tif err := testutils.CheckForHealthCheckLivenessAndReadiness(objects); err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\t}\n}\n\n// TestServiceWithoutPort this tests if Headless Service is created for services without Port.\nfunc TestServiceWithoutPort(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tServiceType:   \"Headless\",\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tif err := testutils.CheckForHeadless(objects); err != nil {\n\t\tt.Error(err)\n\t}\n}\n\n// Tests if deployment strategy is being set to Recreate when volumes are\n// present\nfunc TestRecreateStrategyWithVolumesPresent(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tVolumes:       []kobject.Volumes{{SvcName: \"app\", MountPath: \"/tmp/volume\", PVCName: \"app-claim0\"}},\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objects {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tif deployment.Spec.Strategy.Type != appsv1.RecreateDeploymentStrategyType {\n\t\t\t\tt.Errorf(\"Expected %v as Strategy Type, got %v\",\n\t\t\t\t\tappsv1.RecreateDeploymentStrategyType,\n\t\t\t\t\tdeployment.Spec.Strategy.Type)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSortedKeys(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t}\n\tservice1 := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t}\n\tc := []string{\"a\", \"b\"}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"b\": service, \"a\": service1},\n\t}\n\ta := SortedKeys(komposeObject.ServiceConfigs)\n\tif !reflect.DeepEqual(a, c) {\n\t\tt.Logf(\"Test Fail output should be %s\", c)\n\t}\n}\n\n// test conversion from duration string to seconds *int64\nfunc TestDurationStrToSecondsInt(t *testing.T) {\n\ttestCases := map[string]struct {\n\t\tin  string\n\t\tout *int64\n\t}{\n\t\t\"5s\":         {in: \"5s\", out: &[]int64{5}[0]},\n\t\t\"1m30s\":      {in: \"1m30s\", out: &[]int64{90}[0]},\n\t\t\"empty\":      {in: \"\", out: nil},\n\t\t\"onlynumber\": {in: \"2\", out: nil},\n\t\t\"illegal\":    {in: \"abc\", out: nil},\n\t}\n\n\tfor name, test := range testCases {\n\t\tresult, _ := DurationStrToSecondsInt(test.in)\n\t\tif test.out == nil && result != nil {\n\t\t\tt.Errorf(\"Case '%v' for TestDurationStrToSecondsInt fail, Expected 'nil' , got '%v'\", name, *result)\n\t\t}\n\t\tif test.out != nil && result == nil {\n\t\t\tt.Errorf(\"Case '%v' for TestDurationStrToSecondsInt fail, Expected '%v' , got 'nil'\", name, *test.out)\n\t\t}\n\t\tif test.out != nil && result != nil && *test.out != *result {\n\t\t\tt.Errorf(\"Case '%v' for TestDurationStrToSecondsInt fail, Expected '%v' , got '%v'\", name, *test.out, *result)\n\t\t}\n\t}\n}\n\nfunc TestServiceWithServiceAccount(t *testing.T) {\n\tassertServiceAccountName := \"my-service\"\n\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tPort:          []kobject.Ports{{HostPort: 55555}},\n\t\tLabels:        map[string]string{compose.LabelServiceAccountName: assertServiceAccountName},\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objects {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tif deployment.Spec.Template.Spec.ServiceAccountName != assertServiceAccountName {\n\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", assertServiceAccountName, deployment.Spec.Template.Spec.ServiceAccountName)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCreateServiceWithSpecialName(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"front_end\",\n\t\tImage:         \"nginx\",\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\texpectedContainerName := \"front-end\"\n\tfor _, obj := range objects {\n\t\tif deploy, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tcontainerName := deploy.Spec.Template.Spec.Containers[0].Name\n\t\t\tif containerName != \"front-end\" {\n\t\t\t\tt.Errorf(\"Error while transforming container name. Expected %s Got %s\", expectedContainerName, containerName)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestArgsInterpolation(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"PROTOCOL\", Value: \"https\"}, {Name: \"DOMAIN\", Value: \"google.com\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"curl\"},\n\t\tArgs:          []string{\"$PROTOCOL://$DOMAIN/\"},\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\texpectedArgs := []string{\"$(PROTOCOL)://$(DOMAIN)/\"}\n\tfor _, obj := range objects {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\targs := deployment.Spec.Template.Spec.Containers[0].Args[0]\n\t\t\tif args != expectedArgs[0] {\n\t\t\t\tt.Errorf(\"Expected args %v upon conversion, actual %v\", expectedArgs, args)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestReadOnlyRootFS(t *testing.T) {\n\t// An example service\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tReadOnly:      true,\n\t}\n\n\t// An example object generated via k8s runtime.Objects()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\tk := Kubernetes{}\n\tobjects, err := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\tfor _, obj := range objects {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\treadOnlyFS := deployment.Spec.Template.Spec.Containers[0].SecurityContext.ReadOnlyRootFilesystem\n\t\t\tif *readOnlyFS != true {\n\t\t\t\tt.Errorf(\"Expected ReadOnlyRootFileSystem %v upon conversion, actual %v\", true, readOnlyFS)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestFormatEnvName(t *testing.T) {\n\ttype args struct {\n\t\tname        string\n\t\tserviceName string\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant string\n\t}{\n\t\t{\n\t\t\tname: \"check dot conversion\",\n\t\t\targs: args{\n\t\t\t\tname: \"random.test\",\n\t\t\t},\n\t\t\twant: \"random-test\",\n\t\t},\n\t\t{\n\t\t\tname: \"check that path is shortened\",\n\t\t\targs: args{\n\t\t\t\tname: \"random/test/v1\",\n\t\t\t},\n\t\t\twant: \"random-test-v1\",\n\t\t},\n\t\t{\n\t\t\tname: \"check that ./ is removed\",\n\t\t\targs: args{\n\t\t\t\tname: \"./random\",\n\t\t\t},\n\t\t\twant: \"random\",\n\t\t},\n\t\t{\n\t\t\tname: \"check that everything after $ is removed\",\n\t\t\targs: args{\n\t\t\t\tname: \"abcdefghijklnmopqrstuvxyzabcdefghijklmnopqrstuvwxyzabcdejghijkl$Hereisadditional\",\n\t\t\t},\n\t\t\twant: \"abcdefghijklnmopqrstuvxyzabcdefghijklmnopqrstuvwxyzabcdejghijkl\",\n\t\t},\n\t\t{\n\t\t\tname: \"check that not begins with -\",\n\t\t\targs: args{\n\t\t\t\tname:        \"src/app/.env\",\n\t\t\t\tserviceName: \"app\",\n\t\t\t},\n\t\t\twant: \"src-app--env\",\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := FormatEnvName(tt.args.name, tt.args.serviceName); got != tt.want {\n\t\t\t\tt.Errorf(\"FormatEnvName() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test empty interfaces removal\nfunc TestRemoveEmptyInterfaces(t *testing.T) {\n\ttype Obj = map[string]interface{}\n\tvar testCases = []struct {\n\t\tinput  interface{}\n\t\toutput interface{}\n\t}{\n\t\t{Obj{\"useless\": Obj{}}, Obj{}},\n\t\t{Obj{\"usefull\": Obj{\"usefull\": \"usefull\"}}, Obj{\"usefull\": Obj{\"usefull\": \"usefull\"}}},\n\t\t{Obj{\"usefull\": Obj{\"usefull\": \"usefull\", \"uselessdeep\": Obj{}, \"uselessnil\": nil}}, Obj{\"usefull\": Obj{\"usefull\": \"usefull\"}}},\n\t\t{Obj{\"uselessdeep\": Obj{\"uselessdeep\": Obj{}, \"uselessnil\": nil}}, Obj{}},\n\t\t{Obj{\"uselessempty\": []interface{}{nil}}, Obj{}},\n\t\t{\"test\", \"test\"},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(fmt.Sprintf(\"Test removeEmptyInterfaces(%s)\", tc.input), func(t *testing.T) {\n\t\t\tresult := removeEmptyInterfaces(tc.input)\n\t\t\tif !reflect.DeepEqual(result, tc.output) {\n\t\t\t\tt.Errorf(\"Expected %v, got %v\", tc.output, result)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_parseContainerCommandsFromStr(t *testing.T) {\n\ttests := []struct {\n\t\tname string\n\t\tline string\n\t\twant []string\n\t}{\n\t\t{\n\t\t\tname: \"line command without spaces in between\",\n\t\t\tline: `[ \"bundle\", \"exec\", \"thin\", \"-p\", \"3000\" ]`,\n\t\t\twant: []string{\n\t\t\t\t\"bundle\", \"exec\", \"thin\", \"-p\", \"3000\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `line command spaces inside \"\"`,\n\t\t\tline: `[ \" bundle \",   \" exec \", \" thin \", \" -p \", \"3000\" ]`,\n\t\t\twant: []string{\n\t\t\t\t\"bundle\", \"exec\", \"thin\", \"-p\", \"3000\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `more use cases for line command spaces inside \"\"`,\n\t\t\tline: `[  \" bundle \",   \"exec \",   \" thin \", \" -p \", \"3000  \" ]`,\n\t\t\twant: []string{\n\t\t\t\t\"bundle\", \"exec\", \"thin\", \"-p\", \"3000\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `line command without [] and \"\"`,\n\t\t\tline: `bundle exec thin -p 3000`,\n\t\t\twant: []string{\n\t\t\t\t\"bundle exec thin -p 3000\",\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := parseContainerCommandsFromStr(tt.line); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"parseContainerCommandsFromStr() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_fillInitContainers(t *testing.T) {\n\ttype args struct {\n\t\ttemplate *api.PodTemplateSpec\n\t\tservice  kobject.ServiceConfig\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant []corev1.Container\n\t}{\n\t\t{\n\t\t\tname: \"Testing init container are generated from labels with ,\",\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:    \"name\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage:   \"image\",\n\t\t\t\t\t\tcompose.LabelInitContainerCommand: `[ \"bundle\", \"exec\", \"thin\", \"-p\", \"3000\" ]`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:  \"name\",\n\t\t\t\t\tImage: \"image\",\n\t\t\t\t\tCommand: []string{\n\t\t\t\t\t\t\"bundle\", \"exec\", \"thin\", \"-p\", \"3000\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"Testing init container are generated from labels without ,\",\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:    \"name\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage:   \"image\",\n\t\t\t\t\t\tcompose.LabelInitContainerCommand: `bundle exec thin -p 3000`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:  \"name\",\n\t\t\t\t\tImage: \"image\",\n\t\t\t\t\tCommand: []string{\n\t\t\t\t\t\t`bundle exec thin -p 3000`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `Testing init container with long command with vars inside and ''`,\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:    \"init-myservice\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage:   \"busybox:1.28\",\n\t\t\t\t\t\tcompose.LabelInitContainerCommand: `['sh', '-c', \"until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done\"]`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:  \"init-myservice\",\n\t\t\t\t\tImage: \"busybox:1.28\",\n\t\t\t\t\tCommand: []string{\n\t\t\t\t\t\t\"sh\", \"-c\", `until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `without image`,\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:    \"init-myservice\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage:   \"\",\n\t\t\t\t\t\tcompose.LabelInitContainerCommand: `['sh', '-c', \"until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done\"]`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: nil,\n\t\t},\n\t\t{\n\t\t\tname: `Testing init container without name`,\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:    \"\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage:   \"busybox:1.28\",\n\t\t\t\t\t\tcompose.LabelInitContainerCommand: `['sh', '-c', \"until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done\"]`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:  \"init-service\",\n\t\t\t\t\tImage: \"busybox:1.28\",\n\t\t\t\t\tCommand: []string{\n\t\t\t\t\t\t\"sh\", \"-c\", `until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `Testing init container without command`,\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:    \"init-service\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage:   \"busybox:1.28\",\n\t\t\t\t\t\tcompose.LabelInitContainerCommand: ``,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:    \"init-service\",\n\t\t\t\t\tImage:   \"busybox:1.28\",\n\t\t\t\t\tCommand: []string{},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: `Testing init container without command`,\n\t\t\targs: args{\n\t\t\t\ttemplate: &api.PodTemplateSpec{},\n\t\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelInitContainerName:  \"init-service\",\n\t\t\t\t\t\tcompose.LabelInitContainerImage: \"busybox:1.28\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:    \"init-service\",\n\t\t\t\t\tImage:   \"busybox:1.28\",\n\t\t\t\t\tCommand: []string{},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tfillInitContainers(tt.args.template, tt.args.service)\n\t\t\tif !reflect.DeepEqual(tt.args.template.Spec.InitContainers, tt.want) {\n\t\t\t\tt.Errorf(\"Test_fillInitContainers Fail got %v, want %v\", tt.args.template.Spec.InitContainers, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_getHpaValue(t *testing.T) {\n\ttype args struct {\n\t\tservice      *kobject.ServiceConfig\n\t\tlabel        string\n\t\tdefaultValue int32\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant int32\n\t}{\n\t\t// LabelHpaMinReplicas\n\t\t{\n\t\t\tname: \"LabelHpaMinReplicas with 1 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMinReplicas,\n\t\t\t\tdefaultValue: 1,\n\t\t\t},\n\t\t\twant: 1,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMinReplicas with 0 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"0\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMinReplicas,\n\t\t\t\tdefaultValue: 1,\n\t\t\t},\n\t\t\twant: 0,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMinReplicas with error value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMinReplicas,\n\t\t\t\tdefaultValue: 1,\n\t\t\t},\n\t\t\twant: 1,\n\t\t},\n\t\t// LabelHpaMaxReplicas\n\t\t{\n\t\t\tname: \"LabelHpaMaxReplicas with 10 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMaxReplicas,\n\t\t\t\tdefaultValue: 30,\n\t\t\t},\n\t\t\twant: 10,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMaxReplicas with 0 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"0\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMaxReplicas,\n\t\t\t\tdefaultValue: DefaultMaxReplicas,\n\t\t\t},\n\t\t\twant: 0,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMaxReplicas with error value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMaxReplicas,\n\t\t\t\tdefaultValue: DefaultMaxReplicas,\n\t\t\t},\n\t\t\twant: DefaultMaxReplicas,\n\t\t},\n\t\t// LabelHpaCPU\n\t\t{\n\t\t\tname: \"LabelHpaCPU with 50 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: 30,\n\t\t\t},\n\t\t\twant: 50,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaCPU with 0 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"0\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: 0,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaCPU with error value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: DefaultCPUUtilization,\n\t\t},\n\t\t// LabelHpaMemory\n\t\t{\n\t\t\tname: \"LabelHpaMemory with 70 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: 30,\n\t\t\t},\n\t\t\twant: 70,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMemory with 0 value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"0\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: 0,\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMemory with error value\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"cannot transform\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlabel:        compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: DefaultMemoryUtilization,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := getHpaValue(tt.args.service, tt.args.label, tt.args.defaultValue); got != tt.want {\n\t\t\t\tt.Errorf(\"getHpaValue() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_getResourceHpaValues(t *testing.T) {\n\ttype args struct {\n\t\tservice *kobject.ServiceConfig\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant HpaValues\n\t}{\n\t\t{\n\t\t\tname: \"check default values\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"3\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       1,\n\t\t\t\tMaxReplicas:       3,\n\t\t\t\tCPUtilization:     50,\n\t\t\t\tMemoryUtilization: 70,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check if max replicas are less than min replicas, and max replicas set to min replicas\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"5\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"3\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       5,\n\t\t\t\tMaxReplicas:       5, // same as min replicas\n\t\t\t\tCPUtilization:     50,\n\t\t\t\tMemoryUtilization: 70,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"with error values and use default values from LabelHpaMinReplicas\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"3\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       3,\n\t\t\t\tCPUtilization:     50,\n\t\t\t\tMemoryUtilization: 70,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"LabelHpaMaxReplicas is minor to LabelHpaMinReplicas\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"6\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"5\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       6,\n\t\t\t\tMaxReplicas:       6, // set min replicas number\n\t\t\t\tCPUtilization:     50,\n\t\t\t\tMemoryUtilization: 70,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"error label and LabelHpaMaxReplicas is minor to LabelHpaMinReplicas\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"6\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"5\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       6,\n\t\t\t\tMaxReplicas:       6, // same as min replicas number\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: 70,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"error label and LabelHpaMaxReplicas is minor to LabelHpaMinReplicas and cannot transform hpa mmemor utilization\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"6\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"5\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"cannot transform\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       6,\n\t\t\t\tMaxReplicas:       6,\n\t\t\t\tCPUtilization:     50,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"all error label, set all default values\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"cannot transform\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"error label without some labels, missing labels set to default\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"cannot transform\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"without labels, should return default values\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"only min replicas label is provided\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"3\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       3,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"only max replicas label is provided\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"5\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       5,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check default values when all labels contain invalid values\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"cannot transform\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"cannot transform\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"only cpu utilization label is provided\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"80\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     80,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"only memory utilization label is provided\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"90\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: 90,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"only cpu and memory utilization labels are provided\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU:    \"80\",\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"90\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     80,\n\t\t\t\tMemoryUtilization: 90,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check default values when labels are empty strings\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check default values when labels contain invalid characters\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"abc\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"xyz\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"-100\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"invalid\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check default values when labels are set to zero\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"0\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"0\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"0\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"0\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       0,\n\t\t\t\tMaxReplicas:       0,\n\t\t\t\tCPUtilization:     50,\n\t\t\t\tMemoryUtilization: 70,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check default values when all labels are negative\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"-5\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"-10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"-20\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"-30\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"check default values when labels cpu and memory are over\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"-2\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"-2\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"120\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"120\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: HpaValues{\n\t\t\t\tMinReplicas:       DefaultMinReplicas,\n\t\t\t\tMaxReplicas:       DefaultMaxReplicas,\n\t\t\t\tCPUtilization:     DefaultCPUUtilization,\n\t\t\t\tMemoryUtilization: DefaultMemoryUtilization,\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := getResourceHpaValues(tt.args.service); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"getResourceHpaValues() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_validatePercentageMetric(t *testing.T) {\n\ttype args struct {\n\t\tservice      *kobject.ServiceConfig\n\t\tmetricLabel  string\n\t\tdefaultValue int32\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant int32\n\t}{\n\t\t{\n\t\t\tname: \"0 cpu utilization\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"0\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: 50,\n\t\t},\n\t\t{\n\t\t\tname: \"default cpu valid range\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"120\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: DefaultCPUUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"cpu invalid range\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"-120\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: DefaultCPUUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"cpu utilization set to 100\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"100\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: 100,\n\t\t},\n\t\t{\n\t\t\tname: \"cpu utlization set to 101\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"101\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: DefaultCPUUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"cannot convert value in cpu label\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaCPU: \"not converted\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaCPU,\n\t\t\t\tdefaultValue: DefaultCPUUtilization,\n\t\t\t},\n\t\t\twant: DefaultCPUUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"0 memory utilization\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"0\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: 70,\n\t\t},\n\t\t{\n\t\t\tname: \"memory over 100 utilization\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"120\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: DefaultMemoryUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"-120 utilization memory wrong range\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"-120\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: DefaultMemoryUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"memory 100 usage\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"100\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: 100,\n\t\t},\n\t\t{\n\t\t\tname: \"101 memory utilization\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"101\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: DefaultMemoryUtilization,\n\t\t},\n\t\t{\n\t\t\tname: \"cannot convert memory from label\",\n\t\t\targs: args{\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMemory: \"not converted\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetricLabel:  compose.LabelHpaMemory,\n\t\t\t\tdefaultValue: DefaultMemoryUtilization,\n\t\t\t},\n\t\t\twant: DefaultMemoryUtilization,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := validatePercentageMetric(tt.args.service, tt.args.metricLabel, tt.args.defaultValue); got != tt.want {\n\t\t\t\tt.Errorf(\"validatePercentageMetric() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_getHpaMetricSpec(t *testing.T) {\n\tvalueCPUFixed := int32(50)\n\tvalueMemoryFixed := int32(70)\n\tvalueOver100 := int32(120)\n\tvalueUnderZero := int32(-120)\n\t// valueZero := int32(0)\n\ttype args struct {\n\t\thpaValues HpaValues\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant []hpa.MetricSpec\n\t}{\n\t\t{\n\t\t\tname: \"no values\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{}, // set all values to 0\n\t\t\t},\n\t\t\twant: nil,\n\t\t},\n\t\t{\n\t\t\tname: \"only cpu\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{\n\t\t\t\t\tCPUtilization: valueCPUFixed,\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []hpa.MetricSpec{\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"only memory\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{\n\t\t\t\t\tMemoryUtilization: 70,\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []hpa.MetricSpec{\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"cpu and memory\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{\n\t\t\t\t\tCPUtilization:     valueCPUFixed,\n\t\t\t\t\tMemoryUtilization: valueMemoryFixed,\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []hpa.MetricSpec{\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"memory over 100\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{\n\t\t\t\t\tMemoryUtilization: valueOver100,\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []hpa.MetricSpec{\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueOver100,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"cpu and memory over 100\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{\n\t\t\t\t\tCPUtilization:     valueOver100,\n\t\t\t\t\tMemoryUtilization: valueOver100,\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []hpa.MetricSpec{\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueOver100,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\tAverageUtilization: &valueOver100,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"cpu and memory under 0\",\n\t\t\targs: args{\n\t\t\t\thpaValues: HpaValues{\n\t\t\t\t\tCPUtilization:     valueUnderZero,\n\t\t\t\t\tMemoryUtilization: valueUnderZero,\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: nil,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := getHpaMetricSpec(tt.args.hpaValues); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"getHpaMetricSpec() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_createHPAResources(t *testing.T) {\n\tvalueCPUFixed := int32(50)\n\tvalueMemoryFixed := int32(70)\n\tfixedMinReplicas := int32(1)\n\ttype args struct {\n\t\tname    string\n\t\tservice *kobject.ServiceConfig\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant hpa.HorizontalPodAutoscaler\n\t}{\n\t\t{\n\t\t\tname: \"all labels\",\n\t\t\targs: args{\n\t\t\t\tname: \"web\",\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"10\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: hpa.HorizontalPodAutoscaler{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"web\",\n\t\t\t\t},\n\t\t\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t\t\tName:       \"web\",\n\t\t\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t\t\t},\n\t\t\t\t\tMinReplicas: &fixedMinReplicas,\n\t\t\t\t\tMaxReplicas: 10,\n\t\t\t\t\tMetrics: []hpa.MetricSpec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"minimum labels\",\n\t\t\targs: args{\n\t\t\t\tname: \"api\",\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: hpa.HorizontalPodAutoscaler{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"api\",\n\t\t\t\t},\n\t\t\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t\t\tName:       \"api\",\n\t\t\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t\t\t},\n\t\t\t\t\tMinReplicas: &fixedMinReplicas,\n\t\t\t\t\tMaxReplicas: DefaultMaxReplicas,\n\t\t\t\t\tMetrics: []hpa.MetricSpec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"missing CPU utilization label\",\n\t\t\targs: args{\n\t\t\t\tname: \"app\",\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"5\",\n\t\t\t\t\t\tcompose.LabelHpaMemory:      \"70\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: hpa.HorizontalPodAutoscaler{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"app\",\n\t\t\t\t},\n\t\t\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t\t\tName:       \"app\",\n\t\t\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t\t\t},\n\t\t\t\t\tMinReplicas: &fixedMinReplicas,\n\t\t\t\t\tMaxReplicas: 5,\n\t\t\t\t\tMetrics: []hpa.MetricSpec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"missing memory utilization label\",\n\t\t\targs: args{\n\t\t\t\tname: \"db\",\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"8\",\n\t\t\t\t\t\tcompose.LabelHpaCPU:         \"50\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: hpa.HorizontalPodAutoscaler{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"db\",\n\t\t\t\t},\n\t\t\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t\t\tName:       \"db\",\n\t\t\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t\t\t},\n\t\t\t\t\tMinReplicas: &fixedMinReplicas,\n\t\t\t\t\tMaxReplicas: 8,\n\t\t\t\t\tMetrics: []hpa.MetricSpec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"wrong labels\",\n\t\t\targs: args{\n\t\t\t\tname: \"db\",\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"not converted\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"not converted\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: hpa.HorizontalPodAutoscaler{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"db\",\n\t\t\t\t},\n\t\t\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t\t\tName:       \"db\",\n\t\t\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t\t\t},\n\t\t\t\t\tMinReplicas: &fixedMinReplicas,\n\t\t\t\t\tMaxReplicas: DefaultMaxReplicas,\n\t\t\t\t\tMetrics: []hpa.MetricSpec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"missing both CPU and memory utilization labels\",\n\t\t\targs: args{\n\t\t\t\tname: \"db\",\n\t\t\t\tservice: &kobject.ServiceConfig{\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\tcompose.LabelHpaMinReplicas: \"1\",\n\t\t\t\t\t\tcompose.LabelHpaMaxReplicas: \"5\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: hpa.HorizontalPodAutoscaler{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"HorizontalPodAutoscaler\",\n\t\t\t\t\tAPIVersion: \"autoscaling/v2\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"db\",\n\t\t\t\t},\n\t\t\t\tSpec: hpa.HorizontalPodAutoscalerSpec{\n\t\t\t\t\tScaleTargetRef: hpa.CrossVersionObjectReference{\n\t\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t\t\tName:       \"db\",\n\t\t\t\t\t\tAPIVersion: \"apps/v1\",\n\t\t\t\t\t},\n\t\t\t\t\tMinReplicas: &fixedMinReplicas,\n\t\t\t\t\tMaxReplicas: 5,\n\t\t\t\t\tMetrics: []hpa.MetricSpec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"cpu\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueCPUFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType: hpa.ResourceMetricSourceType,\n\t\t\t\t\t\t\tResource: &hpa.ResourceMetricSource{\n\t\t\t\t\t\t\t\tName: \"memory\",\n\t\t\t\t\t\t\t\tTarget: hpa.MetricTarget{\n\t\t\t\t\t\t\t\t\tType:               hpa.UtilizationMetricType,\n\t\t\t\t\t\t\t\t\tAverageUtilization: &valueMemoryFixed,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := createHPAResources(tt.args.name, tt.args.service); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"createHPAResources() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_setVolumeAccessMode(t *testing.T) {\n\ttype args struct {\n\t\tmode            string\n\t\tvolumeAccesMode []api.PersistentVolumeAccessMode\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant []api.PersistentVolumeAccessMode\n\t}{\n\t\t{\n\t\t\tname: \"readonly\",\n\t\t\targs: args{\n\t\t\t\tmode:            \"ro\",\n\t\t\t\tvolumeAccesMode: []api.PersistentVolumeAccessMode{},\n\t\t\t},\n\t\t\twant: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},\n\t\t},\n\t\t{\n\t\t\tname: \"not acceptable\",\n\t\t\targs: args{\n\t\t\t\tmode:            \"wrong\",\n\t\t\t\tvolumeAccesMode: []api.PersistentVolumeAccessMode{},\n\t\t\t},\n\t\t\twant: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},\n\t\t},\n\t\t{\n\t\t\tname: \"readonly many\",\n\t\t\targs: args{\n\t\t\t\tmode:            \"rox\",\n\t\t\t\tvolumeAccesMode: []api.PersistentVolumeAccessMode{},\n\t\t\t},\n\t\t\twant: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},\n\t\t},\n\t\t{\n\t\t\tname: \"readwrite many\",\n\t\t\targs: args{\n\t\t\t\tmode:            \"rwx\",\n\t\t\t\tvolumeAccesMode: []api.PersistentVolumeAccessMode{},\n\t\t\t},\n\t\t\twant: []api.PersistentVolumeAccessMode{api.ReadWriteMany},\n\t\t},\n\t\t{\n\t\t\tname: \"readwrite once in pod\",\n\t\t\targs: args{\n\t\t\t\tmode:            \"rwop\",\n\t\t\t\tvolumeAccesMode: []api.PersistentVolumeAccessMode{},\n\t\t\t},\n\t\t\twant: []api.PersistentVolumeAccessMode{api.ReadWriteOncePod},\n\t\t},\n\t\t{\n\t\t\tname: \"readwrite once\",\n\t\t\targs: args{\n\t\t\t\tmode:            \"rwo\",\n\t\t\t\tvolumeAccesMode: []api.PersistentVolumeAccessMode{},\n\t\t\t},\n\t\t\twant: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := setVolumeAccessMode(tt.args.mode, tt.args.volumeAccesMode); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"setVolumeAccessMode() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_isConfigFile(t *testing.T) {\n\ttype args struct {\n\t\tfilePath string\n\t}\n\ttests := []struct {\n\t\tname             string\n\t\targs             args\n\t\twantUseConfigMap bool\n\t\twantReadonly     bool\n\t\twantSkip         bool\n\t}{\n\t\t{\n\t\t\tname: \"dir not empty\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"../../../script/test/fixtures/configmap-file-configs/certs\",\n\t\t\t},\n\t\t\twantUseConfigMap: true,\n\t\t\twantReadonly:     true,\n\t\t\twantSkip:         false,\n\t\t},\n\t\t{\n\t\t\tname: \"sock\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"./docker.sock\",\n\t\t\t},\n\t\t\twantUseConfigMap: false,\n\t\t\twantReadonly:     false,\n\t\t\twantSkip:         true,\n\t\t},\n\t\t{\n\t\t\tname: \"cannot resolve filepath\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"./certs/cert1.pem\",\n\t\t\t},\n\t\t\twantUseConfigMap: false,\n\t\t\twantReadonly:     false,\n\t\t\twantSkip:         false,\n\t\t},\n\t\t{\n\t\t\tname: \"file cert\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"../../../script/test/fixtures/configmap-file-configs/certs/cert1.pem\",\n\t\t\t},\n\t\t\twantUseConfigMap: true,\n\t\t\twantReadonly:     true,\n\t\t\twantSkip:         false,\n\t\t},\n\t\t{\n\t\t\tname: \"docker sock\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"/var/run/docker.sock\",\n\t\t\t},\n\t\t\twantUseConfigMap: false,\n\t\t\twantReadonly:     false,\n\t\t\twantSkip:         true,\n\t\t},\n\t\t{\n\t\t\tname: \"file from 3 levels\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"../../../script/test/fixtures/configmap-file-configs/certs-level1/certs-level2/certs-level3/cert2.pem\",\n\t\t\t},\n\t\t\twantUseConfigMap: true,\n\t\t\twantReadonly:     true,\n\t\t\twantSkip:         false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgotUseConfigMap, gotReadonly, gotSkip := isConfigFile(tt.args.filePath)\n\t\t\tif gotUseConfigMap != tt.wantUseConfigMap {\n\t\t\t\tt.Errorf(\"isConfigFile() gotUseConfigMap = %v, want %v\", gotUseConfigMap, tt.wantUseConfigMap)\n\t\t\t}\n\t\t\tif gotReadonly != tt.wantReadonly {\n\t\t\t\tt.Errorf(\"isConfigFile() gotReadonly = %v, want %v\", gotReadonly, tt.wantReadonly)\n\t\t\t}\n\t\t\tif gotSkip != tt.wantSkip {\n\t\t\t\tt.Errorf(\"isConfigFile() gotSkip = %v, want %v\", gotSkip, tt.wantSkip)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_checkIsEmptyDir(t *testing.T) {\n\ttype args struct {\n\t\tfilePath string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    bool\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"dir not found\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"../../../script/test/fixtures/configmap-file-configs/notfound\",\n\t\t\t},\n\t\t\twant:    false,\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"dir not empty\",\n\t\t\targs: args{\n\t\t\t\tfilePath: \"../../../script/test/fixtures/configmap-file-configs/certs\",\n\t\t\t},\n\t\t\twant:    false,\n\t\t\twantErr: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := checkIsEmptyDir(tt.args.filePath)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"checkIsEmptyDir() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"checkIsEmptyDir() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_removeFromSlice(t *testing.T) {\n\ttype args struct {\n\t\tobjects        []runtime.Object\n\t\tobjectToRemove runtime.Object\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant []runtime.Object\n\t}{\n\t\t{\n\t\t\tname: \"remove object in the middle\",\n\t\t\targs: args{\n\t\t\t\tobjects: []runtime.Object{\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove objects in the middle and last object\",\n\t\t\targs: args{\n\t\t\t\tobjects: []runtime.Object{\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove 1 object\",\n\t\t\targs: args{\n\t\t\t\tobjects: []runtime.Object{\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove object at the beginning\",\n\t\t\targs: args{\n\t\t\t\tobjects: []runtime.Object{\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove object at the end\",\n\t\t\targs: args{\n\t\t\t\tobjects: []runtime.Object{\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove object that doesn't exist\",\n\t\t\targs: args{\n\t\t\t\tobjects: []runtime.Object{\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"missing\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove object from empty slice\",\n\t\t\targs: args{\n\t\t\t\tobjects:        []runtime.Object{},\n\t\t\t\tobjectToRemove: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t},\n\t\t\twant: []runtime.Object{},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := removeFromSlice(tt.args.objects, tt.args.objectToRemove); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"removeFromSlice() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_removeTargetDeployment(t *testing.T) {\n\ttype args struct {\n\t\tobjects              *[]runtime.Object\n\t\ttargetDeploymentName string\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant *[]runtime.Object\n\t}{\n\t\t{\n\t\t\tname: \"remove middle object\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\ttargetDeploymentName: \"remove\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove 2 objects from slice\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\ttargetDeploymentName: \"remove\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove 2 object from slice, only persist last one\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\ttargetDeploymentName: \"remove\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove target deployment from an empty slice\",\n\t\t\targs: args{\n\t\t\t\tobjects:              &[]runtime.Object{},\n\t\t\t\ttargetDeploymentName: \"remove\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{},\n\t\t},\n\t\t{\n\t\t\tname: \"remove target deployment that does not exist\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\ttargetDeploymentName: \"missing\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove target deployment from a slice with only the target deployment\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t},\n\t\t\t\ttargetDeploymentName: \"remove\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{},\n\t\t},\n\t\t{\n\t\t\tname: \"remove all targets\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"remove\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t\ttargetDeploymentName: \"remove\",\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tremoveTargetDeployment(tt.args.objects, tt.args.targetDeploymentName)\n\t\t\tif !reflect.DeepEqual(tt.args.objects, tt.want) {\n\t\t\t\tt.Errorf(\"removeFromSlice() = %v, want %v\", tt.args.objects, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_removeDeploymentTransfered(t *testing.T) {\n\ttype args struct {\n\t\tdeploymentMappings []DeploymentMapping\n\t\tobjects            *[]runtime.Object\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant *[]runtime.Object\n\t}{\n\t\t{\n\t\t\tname: \"remove deployment already transferred\",\n\t\t\targs: args{\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove multiple deployments already transferred\",\n\t\t\targs: args{\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tTargetDeploymentName: \"web\",\n\t\t\t\t\t\tSourceDeploymentName: \"cache\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"web\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"cache\"}},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"web\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove deployment transferred with multiple containers\",\n\t\t\targs: args{\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove deployment transferred with different container names\",\n\t\t\targs: args{\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"db\"}},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"remove deployment transferred when no matching source deployment\",\n\t\t\targs: args{\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: &[]runtime.Object{\n\t\t\t\t&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: \"app\"}},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tremoveDeploymentTransfered(tt.args.deploymentMappings, tt.args.objects)\n\t\t\tif !reflect.DeepEqual(tt.args.objects, tt.want) {\n\t\t\t\tt.Errorf(\"removeFromSlice() = %v, want %v\", tt.args.objects, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_searchNetworkModeToService(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tservices map[string]kobject.ServiceConfig\n\t\twant     []DeploymentMapping\n\t}{\n\t\t{\n\t\t\tname: \"search network mode to service\",\n\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\"app\": {\n\t\t\t\t\tName: \"app\",\n\t\t\t\t},\n\t\t\t\t\"db\": {\n\t\t\t\t\tName:        \"db\",\n\t\t\t\t\tNetworkMode: \"service:app\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []DeploymentMapping{\n\t\t\t\t{\n\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"error and not set service:app\",\n\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\"app\": {\n\t\t\t\t\tName: \"app\",\n\t\t\t\t},\n\t\t\t\t\"db\": {\n\t\t\t\t\tName: \"db\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []DeploymentMapping{},\n\t\t},\n\t\t{\n\t\t\tname: \"search network mode to service with multiple source deployments\",\n\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\"app\": {\n\t\t\t\t\tName: \"app\",\n\t\t\t\t},\n\t\t\t\t\"db1\": {\n\t\t\t\t\tName:        \"db1\",\n\t\t\t\t\tNetworkMode: \"service:app\",\n\t\t\t\t},\n\t\t\t\t\"db2\": {\n\t\t\t\t\tName:        \"db2\",\n\t\t\t\t\tNetworkMode: \"service:app\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []DeploymentMapping{\n\t\t\t\t{\n\t\t\t\t\tSourceDeploymentName: \"db1\",\n\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tSourceDeploymentName: \"db2\",\n\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"search network mode to service with multiple target deployments\",\n\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\"app1\": {\n\t\t\t\t\tName: \"app1\",\n\t\t\t\t},\n\t\t\t\t\"app2\": {\n\t\t\t\t\tName: \"app2\",\n\t\t\t\t},\n\t\t\t\t\"db\": {\n\t\t\t\t\tName:        \"db\",\n\t\t\t\t\tNetworkMode: \"service:app1\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: []DeploymentMapping{\n\t\t\t\t{\n\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\tTargetDeploymentName: \"app1\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgotDeploymentMappings := searchNetworkModeToService(tt.services)\n\t\t\tsort.Slice(gotDeploymentMappings, func(i, j int) bool {\n\t\t\t\tif gotDeploymentMappings[i].SourceDeploymentName != gotDeploymentMappings[j].SourceDeploymentName {\n\t\t\t\t\treturn gotDeploymentMappings[i].SourceDeploymentName < gotDeploymentMappings[j].SourceDeploymentName\n\t\t\t\t}\n\t\t\t\treturn gotDeploymentMappings[i].TargetDeploymentName < gotDeploymentMappings[j].TargetDeploymentName\n\t\t\t})\n\t\t\tsort.Slice(tt.want, func(i, j int) bool {\n\t\t\t\tif tt.want[i].SourceDeploymentName != tt.want[j].SourceDeploymentName {\n\t\t\t\t\treturn tt.want[i].SourceDeploymentName < tt.want[j].SourceDeploymentName\n\t\t\t\t}\n\t\t\t\treturn tt.want[i].TargetDeploymentName < tt.want[j].TargetDeploymentName\n\t\t\t})\n\t\t\tif !reflect.DeepEqual(gotDeploymentMappings, tt.want) {\n\t\t\t\tt.Errorf(\"searchNetworkModeToService() = %v, want %v\", gotDeploymentMappings, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_addContainersToTargetDeployment(t *testing.T) {\n\tk := Kubernetes{}\n\n\tappK, err := k.Transform(\n\t\tkobject.KomposeObject{\n\t\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": {\n\t\t\t\tContainerName: \"app\",\n\t\t\t\tImage:         \"image\",\n\t\t\t},\n\t\t\t},\n\t\t}, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\tdbK, err := k.Transform(\n\t\tkobject.KomposeObject{\n\t\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"db\": {\n\t\t\t\tContainerName: \"db\",\n\t\t\t\tImage:         \"image\",\n\t\t\t\tNetworkMode:   \"service:app\",\n\t\t\t},\n\t\t\t},\n\t\t}, kobject.ConvertOptions{CreateD: true, Replicas: 3})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\n\ttype args struct {\n\t\tobjects                  []runtime.Object\n\t\tcontainersToAppend       []api.Container\n\t\tnameDeploymentToTransfer string\n\t}\n\tconst (\n\t\tFirstObject  = 0\n\t\tSecondObject = 1\n\t)\n\ttests := []struct {\n\t\tname         string\n\t\targs         args\n\t\twantAfter    int\n\t\twantBefore   int\n\t\ttargetObject int\n\t}{\n\n\t\t{\n\t\t\tname: \"no containers to add, appk target transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{appK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{},\n\t\t\t\tnameDeploymentToTransfer: \"app\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    1,\n\t\t\ttargetObject: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"no match in the deployment names, no target found\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{dbK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{},\n\t\t\t\tnameDeploymentToTransfer: \"app\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    1,\n\t\t\ttargetObject: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"1 container more, appk target transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{appK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{{Name: \"new-1\"}},\n\t\t\t\tnameDeploymentToTransfer: \"app\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    2,\n\t\t\ttargetObject: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"1 containers and 2 more, appk target transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{appK[0], dbK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{{Name: \"new-1\"}, {Name: \"new-2\"}},\n\t\t\t\tnameDeploymentToTransfer: \"app\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    3,\n\t\t\ttargetObject: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"one containers to transfer, appk target transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{appK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{{Name: \"new-1\"}},\n\t\t\t\tnameDeploymentToTransfer: \"app\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    2,\n\t\t\ttargetObject: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"1 container in appk and add 2 container in dbK, db target transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{appK[0], dbK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{{Name: \"new-1\"}, {Name: \"new-2\"}},\n\t\t\t\tnameDeploymentToTransfer: \"db\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    3,\n\t\t\ttargetObject: SecondObject,\n\t\t},\n\t\t{\n\t\t\tname: \"1 container in appk, cannot add 2 container in dbK, app target transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects:                  []runtime.Object{appK[0], dbK[0]},\n\t\t\t\tcontainersToAppend:       []api.Container{{Name: \"new-1\"}, {Name: \"new-2\"}},\n\t\t\t\tnameDeploymentToTransfer: \"app\",\n\t\t\t},\n\t\t\twantBefore:   1,\n\t\t\twantAfter:    1,\n\t\t\ttargetObject: SecondObject,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tbeforeContainers := (tt.args.objects)[tt.targetObject].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(beforeContainers) != tt.wantBefore {\n\t\t\t\tt.Errorf(\"Before Expected %d containers, got %d\", tt.wantBefore, len(beforeContainers))\n\t\t\t}\n\n\t\t\taddContainersToTargetDeployment(&tt.args.objects, tt.args.containersToAppend, tt.args.nameDeploymentToTransfer)\n\t\t\tafterContainers := (tt.args.objects)[tt.targetObject].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(afterContainers) != tt.wantAfter {\n\t\t\t\tt.Errorf(\"After Expected %d containers, got %d\", tt.wantAfter, len(afterContainers))\n\t\t\t}\n\t\t\t// reset containers\n\t\t\tnewContainer := appK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers[0]\n\t\t\tappK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers = nil\n\t\t\tappK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers = append(appK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers, newContainer)\n\n\t\t\tnewContainer = dbK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers[0]\n\t\t\tdbK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers = nil\n\t\t\tdbK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers = append(dbK[0].(*appsv1.Deployment).Spec.Template.Spec.Containers, newContainer)\n\t\t})\n\t}\n}\n\nfunc Test_addContainersFromSourceToTargetDeployment(t *testing.T) {\n\ttype args struct {\n\t\tobjects              *[]runtime.Object\n\t\tcurrentDeploymentMap DeploymentMapping\n\t}\n\tconst (\n\t\tFirstObject  = 0\n\t\tSecondObject = 1\n\t)\n\ttests := []struct {\n\t\tname             string\n\t\targs             args\n\t\twantBefore       int\n\t\twantAfter        int\n\t\ttargetDeployment int\n\t}{\n\t\t{\n\t\t\tname: \"add one container more to target deployment\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcurrentDeploymentMap: DeploymentMapping{\n\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        2,\n\t\t\ttargetDeployment: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"no containers to transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"new-1\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcurrentDeploymentMap: DeploymentMapping{},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        1,\n\t\t\ttargetDeployment: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"no containers to transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"new-1\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcurrentDeploymentMap: DeploymentMapping{\n\t\t\t\t\tSourceDeploymentName: \"app\",\n\t\t\t\t\tTargetDeploymentName: \"db\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        2,\n\t\t\ttargetDeployment: SecondObject,\n\t\t},\n\t\t{\n\t\t\tname: \"target deployment not found\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"new-1\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcurrentDeploymentMap: DeploymentMapping{\n\t\t\t\t\tSourceDeploymentName: \"no-exist-deployment\",\n\t\t\t\t\tTargetDeploymentName: \"target-no-exist\",\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        1,\n\t\t\ttargetDeployment: FirstObject,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tbeforeContainers := (*tt.args.objects)[tt.targetDeployment].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(beforeContainers) != tt.wantBefore {\n\t\t\t\tt.Errorf(\"Before expected %d containers, got %d\", tt.wantBefore, len(beforeContainers))\n\t\t\t}\n\n\t\t\taddContainersFromSourceToTargetDeployment(tt.args.objects, tt.args.currentDeploymentMap)\n\t\t\tafterContainers := (*tt.args.objects)[tt.targetDeployment].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(afterContainers) != tt.wantAfter {\n\t\t\t\tt.Errorf(\"After expected %d containers, got %d\", tt.wantAfter, len(afterContainers))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_mergeContainersIntoDestinationDeployment(t *testing.T) {\n\ttype args struct {\n\t\tdeploymentMappings []DeploymentMapping\n\t\tobjects            *[]runtime.Object\n\t}\n\tconst (\n\t\tFirstObject  = 0\n\t\tSecondObject = 1\n\t)\n\ttests := []struct {\n\t\tname             string\n\t\targs             args\n\t\twantBefore       int\n\t\twantAfter        int\n\t\ttargetDeployment int\n\t}{\n\t\t{\n\t\t\tname: \"merge containers into db\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tSourceDeploymentName: \"app\",\n\t\t\t\t\t\tTargetDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       0,\n\t\t\twantAfter:        1,\n\t\t\ttargetDeployment: SecondObject,\n\t\t},\n\t\t{\n\t\t\tname: \"merge containers into destination deployment\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-1\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-2\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-3\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        4,\n\t\t\ttargetDeployment: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"no containers to transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdeploymentMappings: []DeploymentMapping{},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        1,\n\t\t\ttargetDeployment: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"merge 2 containers db deployment into app deployment\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-2\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tSourceDeploymentName: \"db\",\n\t\t\t\t\t\tTargetDeploymentName: \"app\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        3,\n\t\t\ttargetDeployment: FirstObject,\n\t\t},\n\t\t{\n\t\t\tname: \"merge containers in app deployment into db deployment\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdeploymentMappings: []DeploymentMapping{\n\t\t\t\t\t{\n\t\t\t\t\t\tSourceDeploymentName: \"app\",\n\t\t\t\t\t\tTargetDeploymentName: \"db\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        2,\n\t\t\ttargetDeployment: SecondObject,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tbeforeContainers := (*tt.args.objects)[tt.targetDeployment].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(beforeContainers) != tt.wantBefore {\n\t\t\t\tt.Errorf(\"Before expected %d containers, got %d\", tt.wantBefore, len(beforeContainers))\n\t\t\t}\n\t\t\tmergeContainersIntoDestinationDeployment(tt.args.deploymentMappings, tt.args.objects)\n\t\t\tafterContainers := (*tt.args.objects)[tt.targetDeployment].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(afterContainers) != tt.wantAfter {\n\t\t\t\tt.Errorf(\"After expected %d containers, got %d\", tt.wantAfter, len(afterContainers))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestKubernetes_fixNetworkModeToService(t *testing.T) {\n\ttype args struct {\n\t\tobjects  *[]runtime.Object\n\t\tservices map[string]kobject.ServiceConfig\n\t}\n\tconst (\n\t\tFirstObject  = 0\n\t\tSecondObject = 1\n\t)\n\ttests := []struct {\n\t\tname             string\n\t\targs             args\n\t\twantBefore       int\n\t\twantAfter        int\n\t\ttargetDeployment int\n\t\twantDeployments  int\n\t}{\n\t\t{\n\t\t\tname: \"fix network mode to service with transfer\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"nginx\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"nginx\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"nginx\": {\n\t\t\t\t\t\tName:  \"nginx\",\n\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t},\n\t\t\t\t\t\"app\": {\n\t\t\t\t\t\tName:        \"app\",\n\t\t\t\t\t\tImage:       \"image\",\n\t\t\t\t\t\tNetworkMode: \"service:db\",\n\t\t\t\t\t},\n\t\t\t\t\t\"db\": {\n\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        2,\n\t\t\ttargetDeployment: FirstObject,\n\t\t\twantDeployments:  2,\n\t\t},\n\t\t{\n\t\t\tname: \"not transfer because wronge service name\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"app\": {\n\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t},\n\t\t\t\t\t\"db\": {\n\t\t\t\t\t\tName:        \"db\",\n\t\t\t\t\t\tImage:       \"image\",\n\t\t\t\t\t\tNetworkMode: \"service:wrong\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        1,\n\t\t\ttargetDeployment: FirstObject,\n\t\t\twantDeployments:  1,\n\t\t},\n\t\t{\n\t\t\tname: \"deployment db removed\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"app\": {\n\t\t\t\t\t\tName:        \"app\",\n\t\t\t\t\t\tImage:       \"image\",\n\t\t\t\t\t\tNetworkMode: \"service:db\",\n\t\t\t\t\t},\n\t\t\t\t\t\"db\": {\n\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        2,\n\t\t\ttargetDeployment: FirstObject, // db deployment removed\n\t\t\twantDeployments:  1,\n\t\t},\n\t\t{\n\t\t\tname: \"deployment app removed and added 1 container\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"app\": {\n\t\t\t\t\t\tName:        \"app\",\n\t\t\t\t\t\tImage:       \"image\",\n\t\t\t\t\t\tNetworkMode: \"service:db\",\n\t\t\t\t\t},\n\t\t\t\t\t\"db\": {\n\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        2,\n\t\t\ttargetDeployment: FirstObject,\n\t\t\twantDeployments:  1,\n\t\t},\n\t\t{\n\t\t\tname: \"deployment db removed and added 3 containers\",\n\t\t\targs: args{\n\t\t\t\tobjects: &[]runtime.Object{\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"app\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"app\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"db\"},\n\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-1\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-2\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tName:  \"db-3\",\n\t\t\t\t\t\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tservices: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"app\": {\n\t\t\t\t\t\tName:        \"app\",\n\t\t\t\t\t\tImage:       \"image\",\n\t\t\t\t\t\tNetworkMode: \"service:db\",\n\t\t\t\t\t},\n\t\t\t\t\t\"db\": {\n\t\t\t\t\t\tName:  \"db\",\n\t\t\t\t\t\tImage: \"image\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantBefore:       1,\n\t\t\twantAfter:        4,\n\t\t\ttargetDeployment: FirstObject, // db deployment removed\n\t\t\twantDeployments:  1,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tk := &Kubernetes{}\n\t\t\tbeforeContainers := (*tt.args.objects)[tt.targetDeployment].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(beforeContainers) != tt.wantBefore {\n\t\t\t\tt.Errorf(\"Expected %d containers, got %d\", tt.wantBefore, len(beforeContainers))\n\t\t\t}\n\n\t\t\tk.fixNetworkModeToService(tt.args.objects, tt.args.services)\n\t\t\tafterContainers := (*tt.args.objects)[tt.targetDeployment].(*appsv1.Deployment).Spec.Template.Spec.Containers\n\t\t\tif len(afterContainers) != tt.wantAfter {\n\t\t\t\tt.Errorf(\"Expected %d containers, got %d\", tt.wantAfter, len(afterContainers))\n\t\t\t}\n\t\t\tif len(*tt.args.objects) != tt.wantDeployments {\n\t\t\t\tt.Errorf(\"Expected %d deployments, got %d\", tt.wantDeployments, len(*tt.args.objects))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/transformer/kubernetes/kubernetes.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage kubernetes\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\t\"github.com/fatih/structs\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/loader/compose\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\t\"github.com/mattn/go-shellwords\"\n\tdeployapi \"github.com/openshift/api/apps/v1\"\n\tbuildapi \"github.com/openshift/api/build/v1\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cast\"\n\t\"golang.org/x/tools/godoc/util\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tbatchv1 \"k8s.io/api/batch/v1\"\n\tapi \"k8s.io/api/core/v1\"\n\tnetworkingv1 \"k8s.io/api/networking/v1\"\n\t\"k8s.io/apimachinery/pkg/api/resource\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\n// Kubernetes implements Transformer interface and represents Kubernetes transformer\ntype Kubernetes struct {\n\t// the user provided options from the command line\n\tOpt kobject.ConvertOptions\n}\n\n// PVCRequestSize (Persistent Volume Claim) has default size\nconst PVCRequestSize = \"100Mi\"\n\n// ValidVolumeSet has the different types of valid volumes\nvar ValidVolumeSet = map[string]struct{}{\"emptyDir\": {}, \"hostPath\": {}, \"configMap\": {}, \"persistentVolumeClaim\": {}}\n\nconst (\n\t// DeploymentController is controller type for Deployment\n\tDeploymentController = \"deployment\"\n\t// DaemonSetController is controller type for DaemonSet\n\tDaemonSetController = \"daemonset\"\n\t// StatefulStateController is controller type for StatefulSet\n\tStatefulStateController = \"statefulset\"\n)\n\n// CheckUnsupportedKey checks if given komposeObject contains\n// keys that are not supported by this transformer.\n// list of all unsupported keys are stored in unsupportedKey variable\n// returns list of TODO: ....\nfunc (k *Kubernetes) CheckUnsupportedKey(komposeObject *kobject.KomposeObject, unsupportedKey map[string]bool) []string {\n\t// collect all keys found in project\n\tvar keysFound []string\n\n\tfor _, serviceConfig := range komposeObject.ServiceConfigs {\n\t\t// this reflection is used in check for empty arrays\n\t\tval := reflect.ValueOf(serviceConfig)\n\t\ts := structs.New(serviceConfig)\n\n\t\tfor _, f := range s.Fields() {\n\t\t\t// Check if given key is among unsupported keys, and skip it if we already saw this key\n\t\t\tif alreadySaw, ok := unsupportedKey[f.Name()]; ok && !alreadySaw {\n\t\t\t\tif f.IsExported() && !f.IsZero() {\n\t\t\t\t\t// IsZero returns false for empty array/slice ([])\n\t\t\t\t\t// this check if field is Slice, and then it checks its size\n\t\t\t\t\tif field := val.FieldByName(f.Name()); field.Kind() == reflect.Slice {\n\t\t\t\t\t\tif field.Len() == 0 {\n\t\t\t\t\t\t\t// array is empty it doesn't matter if it is in unsupportedKey or not\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//get tag from kobject service configure\n\t\t\t\t\ttag := f.Tag(komposeObject.LoadedFrom)\n\t\t\t\t\tkeysFound = append(keysFound, tag)\n\t\t\t\t\tunsupportedKey[f.Name()] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn keysFound\n}\n\n// InitPodSpec creates the pod specification\nfunc (k *Kubernetes) InitPodSpec(name string, image string, pullSecret string) api.PodSpec {\n\tif image == \"\" {\n\t\timage = name\n\t}\n\tpod := api.PodSpec{\n\t\tContainers: []api.Container{\n\t\t\t{\n\t\t\t\tName:  name,\n\t\t\t\tImage: image,\n\t\t\t},\n\t\t},\n\t}\n\tif pullSecret != \"\" {\n\t\tpod.ImagePullSecrets = []api.LocalObjectReference{\n\t\t\t{\n\t\t\t\tName: pullSecret,\n\t\t\t},\n\t\t}\n\t}\n\treturn pod\n}\n\n// InitPodSpecWithConfigMap creates the pod specification\nfunc (k *Kubernetes) InitPodSpecWithConfigMap(name string, image string, service kobject.ServiceConfig) api.PodSpec {\n\tvar volumeMounts []api.VolumeMount\n\tvar volumes []api.Volume\n\n\tfor _, value := range service.Configs {\n\t\tcmVolName := FormatFileName(value.Source)\n\t\ttarget := value.Target\n\t\tif target == \"\" {\n\t\t\t// short syntax, = /<source>\n\t\t\ttarget = \"/\" + value.Source\n\t\t}\n\t\tsubPath := filepath.Base(target)\n\n\t\tvolSource := api.ConfigMapVolumeSource{}\n\t\tvolSource.Name = cmVolName\n\t\tkey, err := service.GetConfigMapKeyFromMeta(value.Source)\n\t\tif err != nil {\n\t\t\tlog.Warnf(\"cannot parse config %s , %s\", value.Source, err.Error())\n\t\t\t// mostly it's external\n\t\t\tcontinue\n\t\t}\n\t\tvolSource.Items = []api.KeyToPath{{\n\t\t\tKey:  key,\n\t\t\tPath: subPath,\n\t\t}}\n\n\t\tif value.Mode != nil {\n\t\t\ttmpMode := int32(*value.Mode)\n\t\t\tvolSource.DefaultMode = &tmpMode\n\t\t}\n\n\t\tcmVol := api.Volume{\n\t\t\tName:         cmVolName,\n\t\t\tVolumeSource: api.VolumeSource{ConfigMap: &volSource},\n\t\t}\n\n\t\tvolumeMounts = append(volumeMounts,\n\t\t\tapi.VolumeMount{\n\t\t\t\tName:      cmVolName,\n\t\t\t\tMountPath: target,\n\t\t\t\tSubPath:   subPath,\n\t\t\t})\n\t\tvolumes = append(volumes, cmVol)\n\t}\n\n\tpod := api.PodSpec{\n\t\tContainers: []api.Container{\n\t\t\t{\n\t\t\t\tName:         name,\n\t\t\t\tImage:        image,\n\t\t\t\tVolumeMounts: volumeMounts,\n\t\t\t},\n\t\t},\n\t\tVolumes: volumes,\n\t}\n\n\tif service.ImagePullSecret != \"\" {\n\t\tpod.ImagePullSecrets = []api.LocalObjectReference{\n\t\t\t{\n\t\t\t\tName: service.ImagePullSecret,\n\t\t\t},\n\t\t}\n\t}\n\treturn pod\n}\n\n// InitSvc initializes Kubernetes Service object\n// The created service name will = ServiceConfig.Name, but the selector may be not.\n// If this service is grouped, the selector may be another name = name\nfunc (k *Kubernetes) InitSvc(name string, service kobject.ServiceConfig) *api.Service {\n\tsvc := &api.Service{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"Service\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   service.Name,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t\t// The selector uses the service.Name, which must be consistent with workloads label\n\t\tSpec: api.ServiceSpec{\n\t\t\tSelector: transformer.ConfigLabels(name),\n\t\t},\n\t}\n\treturn svc\n}\n\n// InitConfigMapForEnvWithLookup initializes a ConfigMap object from an env_file with variable interpolation support\n// using the provided lookup function to resolve variable references like ${VAR} or ${VAR:-default}\nfunc (k *Kubernetes) InitConfigMapForEnvWithLookup(name string, opt kobject.ConvertOptions, envFile string, lookup func(key string) (string, bool)) *api.ConfigMap {\n\tworkDir, err := transformer.GetComposeFileDir(opt.InputFiles)\n\tif err != nil {\n\t\tlog.Fatalf(\"Unable to get compose file directory: %s\", err)\n\t}\n\tenvs, err := LoadEnvFiles(filepath.Join(workDir, envFile), lookup)\n\tif err != nil {\n\t\tlog.Fatalf(\"Unable to retrieve env file: %s\", err)\n\t}\n\n\t// Remove root pathing\n\t// replace all other slashes / periods\n\tenvName := FormatEnvName(envFile, name)\n\n\t// In order to differentiate files, we append to the name and remove '.env' if applicable from the file name\n\tconfigMap := &api.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"ConfigMap\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   envName,\n\t\t\tLabels: transformer.ConfigLabels(name + \"-\" + envName),\n\t\t},\n\t\tData: envs,\n\t}\n\n\treturn configMap\n}\n\n// InitConfigMapForEnv initializes a ConfigMap object\nfunc (k *Kubernetes) InitConfigMapForEnv(name string, opt kobject.ConvertOptions, envFile string) *api.ConfigMap {\n\tworkDir, err := transformer.GetComposeFileDir(opt.InputFiles)\n\tif err != nil {\n\t\tlog.Fatalf(\"Unable to get compose file directory: %s\", err)\n\t}\n\tenvs, err := GetEnvsFromFile(filepath.Join(workDir, envFile))\n\tif err != nil {\n\t\tlog.Fatalf(\"Unable to retrieve env file: %s\", err)\n\t}\n\n\t// Remove root pathing\n\t// replace all other slashes / periods\n\tenvName := FormatEnvName(envFile, name)\n\n\t// In order to differentiate files, we append to the name and remove '.env' if applicable from the file name\n\tconfigMap := &api.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"ConfigMap\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   envName,\n\t\t\tLabels: transformer.ConfigLabels(name + \"-\" + envName),\n\t\t},\n\t\tData: envs,\n\t}\n\n\treturn configMap\n}\n\n// IntiConfigMapFromFileOrDir will create a configmap from dir or file\n// usage:\n//  1. volume\nfunc (k *Kubernetes) IntiConfigMapFromFileOrDir(name, cmName, filePath string, service kobject.ServiceConfig) (*api.ConfigMap, error) {\n\tconfigMap := &api.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"ConfigMap\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   cmName,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t}\n\tdataMap := make(map[string]string)\n\n\tfi, err := os.Stat(filePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tswitch mode := fi.Mode(); {\n\tcase mode.IsDir():\n\t\tfiles, err := os.ReadDir(filePath)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tfor _, file := range files {\n\t\t\tif !file.IsDir() {\n\t\t\t\tlog.Debugf(\"Read file to ConfigMap: %s\", file.Name())\n\t\t\t\tdata, err := GetContentFromFile(filePath + \"/\" + file.Name())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tdataMap[file.Name()] = data\n\t\t\t}\n\t\t}\n\t\tinitConfigMapData(configMap, dataMap)\n\n\tcase mode.IsRegular():\n\t\t// do file stuff\n\t\tconfigMap = k.InitConfigMapFromFile(name, service, filePath)\n\t\tconfigMap.Name = cmName\n\t\tconfigMap.Annotations = map[string]string{\n\t\t\t\"use-subpath\": \"true\",\n\t\t}\n\t}\n\n\treturn configMap, nil\n}\n\n// useSubPathMount check if a configmap should be mounted as subpath\n// in this situation, this configmap will only contains 1 key in data\nfunc useSubPathMount(cm *api.ConfigMap) bool {\n\tif cm.Annotations == nil {\n\t\treturn false\n\t}\n\tif cm.Annotations[\"use-subpath\"] != \"true\" {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc initConfigMapData(configMap *api.ConfigMap, data map[string]string) {\n\tstringData := map[string]string{}\n\tbinData := map[string][]byte{}\n\n\tfor k, v := range data {\n\t\tlfText := strings.Replace(v, \"\\r\\n\", \"\\n\", -1)\n\t\tisText := util.IsText([]byte(lfText))\n\t\tif isText {\n\t\t\tstringData[k] = lfText\n\t\t} else {\n\t\t\tbinData[k] = []byte(base64.StdEncoding.EncodeToString([]byte(v)))\n\t\t}\n\t}\n\n\tconfigMap.Data = stringData\n\tconfigMap.BinaryData = binData\n}\n\n// InitConfigMapFromContent initializes a ConfigMap object\nfunc (k *Kubernetes) InitConfigMapFromContent(name string, service kobject.ServiceConfig, content string, currentConfigName string, target string) *api.ConfigMap {\n\tconfigMap := &api.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"ConfigMap\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   currentConfigName,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t}\n\tfilename := GetFileName(target)\n\tdata := map[string]string{filename: content}\n\tinitConfigMapData(configMap, data)\n\treturn configMap\n}\n\n// InitConfigMapFromFile initializes a ConfigMap object\nfunc (k *Kubernetes) InitConfigMapFromFile(name string, service kobject.ServiceConfig, fileName string) *api.ConfigMap {\n\tcontent, err := GetContentFromFile(fileName)\n\tif err != nil {\n\t\tlog.Fatalf(\"Unable to retrieve file: %s\", err)\n\t}\n\n\tconfigMapName := \"\"\n\tfor key, tmpConfig := range service.ConfigsMetaData {\n\t\tif tmpConfig.File == fileName {\n\t\t\tconfigMapName = key\n\t\t}\n\t}\n\tconfigMap := &api.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"ConfigMap\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   FormatFileName(configMapName),\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t}\n\n\tdata := map[string]string{filepath.Base(fileName): content}\n\tinitConfigMapData(configMap, data)\n\treturn configMap\n}\n\n// InitD initializes Kubernetes Deployment object\nfunc (k *Kubernetes) InitD(name string, service kobject.ServiceConfig, replicas int) *appsv1.Deployment {\n\tvar podSpec api.PodSpec\n\tif len(service.Configs) > 0 {\n\t\tpodSpec = k.InitPodSpecWithConfigMap(name, service.Image, service)\n\t} else {\n\t\tpodSpec = k.InitPodSpec(name, service.Image, service.ImagePullSecret)\n\t}\n\n\trp := int32(replicas)\n\n\tdc := &appsv1.Deployment{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"Deployment\",\n\t\t\tAPIVersion: \"apps/v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigAllLabels(name, &service),\n\t\t},\n\t\tSpec: appsv1.DeploymentSpec{\n\t\t\tReplicas: &rp,\n\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: transformer.ConfigLabels(name),\n\t\t\t},\n\t\t\tTemplate: api.PodTemplateSpec{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t//Labels: transformer.ConfigLabels(name),\n\t\t\t\t\tAnnotations: transformer.ConfigAnnotations(service),\n\t\t\t\t},\n\t\t\t\tSpec: podSpec,\n\t\t\t},\n\t\t},\n\t}\n\tdc.Spec.Template.Labels = transformer.ConfigLabels(name)\n\n\tupdate := service.GetKubernetesUpdateStrategy()\n\tif update != nil {\n\t\tdc.Spec.Strategy = appsv1.DeploymentStrategy{\n\t\t\tType:          appsv1.RollingUpdateDeploymentStrategyType,\n\t\t\tRollingUpdate: update,\n\t\t}\n\t\tms := \"\"\n\t\tif update.MaxSurge != nil {\n\t\t\tms = update.MaxSurge.String()\n\t\t}\n\t\tmu := \"\"\n\t\tif update.MaxUnavailable != nil {\n\t\t\tmu = update.MaxUnavailable.String()\n\t\t}\n\t\tlog.Debugf(\"Set deployment '%s' rolling update: MaxSurge: %s, MaxUnavailable: %s\", name, ms, mu)\n\t}\n\n\treturn dc\n}\n\n// InitDS initializes Kubernetes DaemonSet object\nfunc (k *Kubernetes) InitDS(name string, service kobject.ServiceConfig) *appsv1.DaemonSet {\n\tds := &appsv1.DaemonSet{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"DaemonSet\",\n\t\t\tAPIVersion: \"apps/v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigAllLabels(name, &service),\n\t\t},\n\t\tSpec: appsv1.DaemonSetSpec{\n\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: transformer.ConfigLabels(name),\n\t\t\t},\n\t\t\tTemplate: api.PodTemplateSpec{\n\t\t\t\tSpec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),\n\t\t\t},\n\t\t},\n\t}\n\treturn ds\n}\n\n// InitSS method initialize a stateful set\nfunc (k *Kubernetes) InitSS(name string, service kobject.ServiceConfig, replicas int) *appsv1.StatefulSet {\n\tvar podSpec api.PodSpec\n\tif len(service.Configs) > 0 {\n\t\tpodSpec = k.InitPodSpecWithConfigMap(name, service.Image, service)\n\t} else {\n\t\tpodSpec = k.InitPodSpec(name, service.Image, service.ImagePullSecret)\n\t}\n\trp := int32(replicas)\n\tds := &appsv1.StatefulSet{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"StatefulSet\",\n\t\t\tAPIVersion: \"apps/v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigAllLabels(name, &service),\n\t\t},\n\t\tSpec: appsv1.StatefulSetSpec{\n\t\t\tReplicas: &rp,\n\t\t\tTemplate: api.PodTemplateSpec{\n\t\t\t\tSpec: podSpec,\n\t\t\t},\n\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: transformer.ConfigLabels(name),\n\t\t\t},\n\t\t\tServiceName: service.Name,\n\t\t},\n\t}\n\treturn ds\n}\n\n// InitCJ initializes Kubernetes CronJob object\nfunc (k *Kubernetes) InitCJ(name string, service kobject.ServiceConfig, schedule string, concurrencyPolicy batchv1.ConcurrencyPolicy, backoffLimit *int32) *batchv1.CronJob {\n\tcj := &batchv1.CronJob{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"CronJob\",\n\t\t\tAPIVersion: \"batch/v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigAllLabels(name, &service),\n\t\t},\n\t\tSpec: batchv1.CronJobSpec{\n\t\t\tSchedule:          schedule,\n\t\t\tConcurrencyPolicy: concurrencyPolicy,\n\t\t\tJobTemplate: batchv1.JobTemplateSpec{\n\t\t\t\tSpec: batchv1.JobSpec{\n\t\t\t\t\tBackoffLimit: backoffLimit,\n\t\t\t\t\tTemplate: api.PodTemplateSpec{\n\t\t\t\t\t\tSpec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\treturn cj\n}\n\nfunc (k *Kubernetes) initIngress(name string, service kobject.ServiceConfig, port int32) *networkingv1.Ingress {\n\thosts := regexp.MustCompile(\"[ ,]*,[ ,]*\").Split(service.ExposeService, -1)\n\n\tingress := &networkingv1.Ingress{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"Ingress\",\n\t\t\tAPIVersion: \"networking.k8s.io/v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:        name,\n\t\t\tLabels:      transformer.ConfigLabels(name),\n\t\t\tAnnotations: transformer.ConfigAnnotations(service),\n\t\t},\n\t\tSpec: networkingv1.IngressSpec{\n\t\t\tRules: make([]networkingv1.IngressRule, len(hosts)),\n\t\t},\n\t}\n\ttlsHosts := make([]string, len(hosts))\n\tpathType := networkingv1.PathTypePrefix\n\tfor i, host := range hosts {\n\t\thost, p := transformer.ParseIngressPath(host)\n\t\tif p == \"\" {\n\t\t\tp = \"/\"\n\t\t}\n\t\tingress.Spec.Rules[i] = networkingv1.IngressRule{\n\t\t\tIngressRuleValue: networkingv1.IngressRuleValue{\n\t\t\t\tHTTP: &networkingv1.HTTPIngressRuleValue{\n\t\t\t\t\tPaths: []networkingv1.HTTPIngressPath{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPath:     p,\n\t\t\t\t\t\t\tPathType: &pathType,\n\t\t\t\t\t\t\tBackend: networkingv1.IngressBackend{\n\t\t\t\t\t\t\t\tService: &networkingv1.IngressServiceBackend{\n\t\t\t\t\t\t\t\t\tName: name,\n\t\t\t\t\t\t\t\t\tPort: networkingv1.ServiceBackendPort{\n\t\t\t\t\t\t\t\t\t\tNumber: port,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tif host != \"true\" {\n\t\t\tingress.Spec.Rules[i].Host = host\n\t\t\ttlsHosts[i] = host\n\t\t}\n\t}\n\tif service.ExposeServiceTLS != \"\" {\n\t\tif service.ExposeServiceTLS != \"true\" {\n\t\t\tingress.Spec.TLS = []networkingv1.IngressTLS{\n\t\t\t\t{\n\t\t\t\t\tHosts:      tlsHosts,\n\t\t\t\t\tSecretName: service.ExposeServiceTLS,\n\t\t\t\t},\n\t\t\t}\n\t\t} else {\n\t\t\tingress.Spec.TLS = []networkingv1.IngressTLS{\n\t\t\t\t{\n\t\t\t\t\tHosts: tlsHosts,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t}\n\n\tif service.ExposeServiceIngressClassName != \"\" {\n\t\tingress.Spec.IngressClassName = &service.ExposeServiceIngressClassName\n\t}\n\n\treturn ingress\n}\n\n// CreateSecrets create secrets\nfunc (k *Kubernetes) CreateSecrets(komposeObject kobject.KomposeObject) ([]*api.Secret, error) {\n\tvar objects []*api.Secret\n\tfor name, config := range komposeObject.Secrets {\n\t\tif config.File != \"\" {\n\t\t\tdataString, err := GetContentFromFile(config.File)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatal(\"unable to read secret from file: \", config.File)\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdata := []byte(dataString)\n\t\t\tresourceName := FormatResourceName(name)\n\t\t\tsecret := &api.Secret{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tKind:       \"Secret\",\n\t\t\t\t\tAPIVersion: \"v1\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:   resourceName,\n\t\t\t\t\tLabels: transformer.ConfigLabels(resourceName),\n\t\t\t\t},\n\t\t\t\tType: api.SecretTypeOpaque,\n\t\t\t\tData: map[string][]byte{resourceName: data},\n\t\t\t}\n\t\t\tobjects = append(objects, secret)\n\t\t} else {\n\t\t\tlog.Warnf(\"External secrets %s is not currently supported - ignoring\", name)\n\t\t}\n\t}\n\treturn objects, nil\n}\n\n// CreatePVC initializes PersistentVolumeClaim\nfunc (k *Kubernetes) CreatePVC(name string, mode string, size string, selectorValue string, storageClassName string) (*api.PersistentVolumeClaim, error) {\n\tvolSize, err := resource.ParseQuantity(size)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"resource.ParseQuantity failed, Error parsing size\")\n\t}\n\n\tpvc := &api.PersistentVolumeClaim{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"PersistentVolumeClaim\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   FormatResourceName(name),\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t\tSpec: api.PersistentVolumeClaimSpec{\n\t\t\tResources: api.VolumeResourceRequirements{\n\t\t\t\tRequests: api.ResourceList{\n\t\t\t\t\tapi.ResourceStorage: volSize,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tif len(selectorValue) > 0 {\n\t\tpvc.Spec.Selector = &metav1.LabelSelector{\n\t\t\tMatchLabels: transformer.ConfigLabels(selectorValue),\n\t\t}\n\t}\n\n\tpvc.Spec.AccessModes = setVolumeAccessMode(mode, pvc.Spec.AccessModes)\n\n\tif len(storageClassName) > 0 {\n\t\tpvc.Spec.StorageClassName = &storageClassName\n\t}\n\n\treturn pvc, nil\n}\n\n// ConfigPorts configures the container ports.\nfunc ConfigPorts(service kobject.ServiceConfig) []api.ContainerPort {\n\tvar ports []api.ContainerPort\n\texist := map[string]bool{}\n\tfor _, port := range service.Port {\n\t\tif exist[port.ID()] {\n\t\t\tcontinue\n\t\t}\n\t\tcontainerPort := api.ContainerPort{\n\t\t\tContainerPort: port.ContainerPort,\n\t\t\tProtocol:      api.Protocol(port.Protocol),\n\t\t}\n\n\t\tif service.ExposeContainerToHost {\n\t\t\tcontainerPort.HostIP = port.HostIP\n\t\t\tcontainerPort.HostPort = port.HostPort\n\t\t}\n\t\tports = append(ports, containerPort)\n\t\texist[port.ID()] = true\n\t}\n\n\treturn ports\n}\n\n// ConfigLBServicePorts method configure the ports of the k8s Load Balancer Service\nfunc (k *Kubernetes) ConfigLBServicePorts(service kobject.ServiceConfig) ([]api.ServicePort, []api.ServicePort) {\n\tvar tcpPorts []api.ServicePort\n\tvar udpPorts []api.ServicePort\n\tfor _, port := range service.Port {\n\t\tif port.HostPort == 0 {\n\t\t\tport.HostPort = port.ContainerPort\n\t\t}\n\t\tvar targetPort intstr.IntOrString\n\t\ttargetPort.IntVal = port.ContainerPort\n\t\ttargetPort.StrVal = strconv.Itoa(int(port.ContainerPort))\n\n\t\tservicePort := api.ServicePort{\n\t\t\tName:       strconv.Itoa(int(port.HostPort)),\n\t\t\tPort:       port.HostPort,\n\t\t\tTargetPort: targetPort,\n\t\t}\n\n\t\tif protocol := api.Protocol(port.Protocol); protocol == api.ProtocolTCP {\n\t\t\t// If the default is already TCP, no need to include protocol.\n\t\t\ttcpPorts = append(tcpPorts, servicePort)\n\t\t} else {\n\t\t\tservicePort.Protocol = protocol\n\t\t\tudpPorts = append(udpPorts, servicePort)\n\t\t}\n\t}\n\treturn tcpPorts, udpPorts\n}\n\n// ConfigServicePorts configure the container service ports.\nfunc (k *Kubernetes) ConfigServicePorts(service kobject.ServiceConfig) []api.ServicePort {\n\tservicePorts := []api.ServicePort{}\n\tseenPorts := make(map[int]struct{}, len(service.Port))\n\n\tvar servicePort api.ServicePort\n\tfor _, port := range service.Port {\n\t\tif port.HostPort == 0 {\n\t\t\tport.HostPort = port.ContainerPort\n\t\t}\n\n\t\tvar targetPort intstr.IntOrString\n\t\ttargetPort.IntVal = port.ContainerPort\n\t\ttargetPort.StrVal = strconv.Itoa(int(port.ContainerPort))\n\n\t\t// decide the name based on whether we saw this port before\n\t\tname := strconv.Itoa(int(port.HostPort))\n\t\tif _, ok := seenPorts[int(port.HostPort)]; ok {\n\t\t\t// https://github.com/kubernetes/kubernetes/issues/2995\n\t\t\tif service.ServiceType == string(api.ServiceTypeLoadBalancer) {\n\t\t\t\tlog.Fatalf(\"Service %s of type LoadBalancer cannot use TCP and UDP for the same port\", name)\n\t\t\t}\n\t\t\tname = fmt.Sprintf(\"%s-%s\", name, strings.ToLower(port.Protocol))\n\t\t}\n\n\t\tservicePort = api.ServicePort{\n\t\t\tName:       name,\n\t\t\tPort:       port.HostPort,\n\t\t\tTargetPort: targetPort,\n\t\t}\n\n\t\tif service.ServiceType == string(api.ServiceTypeNodePort) && service.NodePortPort != 0 {\n\t\t\tservicePort.NodePort = service.NodePortPort\n\t\t}\n\n\t\t// If the default is already TCP, no need to include protocol.\n\t\tif protocol := api.Protocol(port.Protocol); protocol != api.ProtocolTCP {\n\t\t\tservicePort.Protocol = protocol\n\t\t}\n\n\t\tservicePorts = append(servicePorts, servicePort)\n\t\tseenPorts[int(port.HostPort)] = struct{}{}\n\t}\n\treturn servicePorts\n}\n\n// ConfigCapabilities configure POSIX capabilities that can be added or removed to a container\nfunc ConfigCapabilities(service kobject.ServiceConfig) *api.Capabilities {\n\tcapsAdd := []api.Capability{}\n\tcapsDrop := []api.Capability{}\n\tfor _, capAdd := range service.CapAdd {\n\t\tcapsAdd = append(capsAdd, api.Capability(capAdd))\n\t}\n\tfor _, capDrop := range service.CapDrop {\n\t\tcapsDrop = append(capsDrop, api.Capability(capDrop))\n\t}\n\treturn &api.Capabilities{\n\t\tAdd:  capsAdd,\n\t\tDrop: capsDrop,\n\t}\n}\n\n// ConfigTmpfs configure the tmpfs.\nfunc (k *Kubernetes) ConfigTmpfs(name string, service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume) {\n\t//initializing volumemounts and volumes\n\tvolumeMounts := []api.VolumeMount{}\n\tvolumes := []api.Volume{}\n\n\tfor index, volume := range service.TmpFs {\n\t\t//naming volumes if multiple tmpfs are provided\n\t\tvolumeName := fmt.Sprintf(\"%s-tmpfs%d\", name, index)\n\t\tvolume = strings.Split(volume, \":\")[0]\n\t\t// create a new volume mount object and append to list\n\t\tvolMount := api.VolumeMount{\n\t\t\tName:      volumeName,\n\t\t\tMountPath: volume,\n\t\t}\n\t\tvolumeMounts = append(volumeMounts, volMount)\n\n\t\t//create tmpfs specific empty volumes\n\t\tvolSource := k.ConfigEmptyVolumeSource(\"tmpfs\")\n\n\t\t// create a new volume object using the volsource and add to list\n\t\tvol := api.Volume{\n\t\t\tName:         volumeName,\n\t\t\tVolumeSource: *volSource,\n\t\t}\n\t\tvolumes = append(volumes, vol)\n\t}\n\treturn volumeMounts, volumes\n}\n\n// ConfigSecretVolumes config volumes from secret.\n// Link: https://docs.docker.com/compose/compose-file/#secrets\n// In kubernetes' Secret resource, it has a data structure like a map[string]bytes, every key will act like the file name\n// when mount to a container. This is the part that missing in compose. So we will create a single key secret from compose\n// config and the key's name will be the secret's name, it's value is the file content.\n// compose's secret can only be mounted at `/run/secrets`, so this will be hardcoded.\nfunc (k *Kubernetes) ConfigSecretVolumes(name string, service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume) {\n\tvar volumeMounts []api.VolumeMount\n\tvar volumes []api.Volume\n\tif len(service.Secrets) > 0 {\n\t\tfor _, secretConfig := range service.Secrets {\n\t\t\tsecretConfig := reformatSecretConfigUnderscoreWithDash(secretConfig)\n\t\t\tif secretConfig.UID != \"\" {\n\t\t\t\tlog.Warnf(\"Ignore pid in secrets for service: %s\", name)\n\t\t\t}\n\t\t\tif secretConfig.GID != \"\" {\n\t\t\t\tlog.Warnf(\"Ignore gid in secrets for service: %s\", name)\n\t\t\t}\n\n\t\t\tvar secretItemPath, secretMountPath, secretSubPath string\n\t\t\tif k.Opt.SecretsAsFiles {\n\t\t\t\tsecretItemPath, secretMountPath, secretSubPath = k.getSecretPaths(secretConfig)\n\t\t\t} else {\n\t\t\t\tsecretItemPath, secretMountPath, secretSubPath = k.getSecretPathsLegacy(secretConfig)\n\t\t\t}\n\n\t\t\tvolSource := api.VolumeSource{\n\t\t\t\tSecret: &api.SecretVolumeSource{\n\t\t\t\t\tSecretName: secretConfig.Source,\n\t\t\t\t\tItems: []api.KeyToPath{{\n\t\t\t\t\t\tKey:  secretConfig.Source,\n\t\t\t\t\t\tPath: secretItemPath,\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tif secretConfig.Mode != nil {\n\t\t\t\tmode := cast.ToInt32(*secretConfig.Mode)\n\t\t\t\tvolSource.Secret.DefaultMode = &mode\n\t\t\t}\n\n\t\t\tvol := api.Volume{\n\t\t\t\tName:         secretConfig.Source,\n\t\t\t\tVolumeSource: volSource,\n\t\t\t}\n\t\t\tvolumes = append(volumes, vol)\n\n\t\t\tvolMount := api.VolumeMount{\n\t\t\t\tName:      vol.Name,\n\t\t\t\tMountPath: secretMountPath,\n\t\t\t\tSubPath:   secretSubPath,\n\t\t\t}\n\t\t\tvolumeMounts = append(volumeMounts, volMount)\n\t\t}\n\t}\n\treturn volumeMounts, volumes\n}\n\nfunc (k *Kubernetes) getSecretPaths(secretConfig types.ServiceSecretConfig) (secretItemPath, secretMountPath, secretSubPath string) {\n\t// Default secretConfig.Target to secretConfig.Source, just in case user was using short secret syntax or\n\t// otherwise did not define a specific target\n\ttarget := secretConfig.Target\n\tif target == \"\" {\n\t\ttarget = secretConfig.Source\n\t}\n\n\t// If target is an absolute path, set that as the MountPath\n\tif strings.HasPrefix(secretConfig.Target, \"/\") {\n\t\tsecretMountPath = target\n\t} else {\n\t\t// If target is a relative path, prefix with \"/run/secrets/\" to replicate what docker-compose would do\n\t\tsecretMountPath = \"/run/secrets/\" + target\n\t}\n\n\t// Set subPath to the target filename. this ensures that we end up with a file at our MountPath instead\n\t// of a directory with symlinks (see https://stackoverflow.com/a/68332231)\n\tsplitPath := strings.Split(target, \"/\")\n\tsecretFilename := splitPath[len(splitPath)-1]\n\n\t// `secretItemPath` and `secretSubPath` have to be the same as `secretFilename` to ensure we create a file with\n\t// that name at `secretMountPath`, instead of a directory containing a symlink to the actual file.\n\tsecretItemPath = secretFilename\n\tsecretSubPath = secretFilename\n\n\treturn secretItemPath, secretMountPath, secretSubPath\n}\n\nfunc (k *Kubernetes) getSecretPathsLegacy(secretConfig types.ServiceSecretConfig) (secretItemPath, secretMountPath, secretSubPath string) {\n\t// The old way of setting secret paths. It resulted in files being placed in incorrect locations when compared to\n\t// docker-compose results, but some people might depend on this behavior so this is kept here for compatibility.\n\t// See https://github.com/kubernetes/kompose/issues/1280 for more details.\n\n\tvar itemPath string // should be the filename\n\tvar mountPath = \"\"  // should be the directory\n\t// if is used the short-syntax\n\tif secretConfig.Target == \"\" {\n\t\t// the secret path (mountPath) should be inside the default directory /run/secrets\n\t\tmountPath = \"/run/secrets/\" + secretConfig.Source\n\t\t// the itemPath should be the source itself\n\t\titemPath = secretConfig.Source\n\t} else {\n\t\t// if is the long-syntax, i should get the last part of path and consider it the filename\n\t\tpathSplitted := strings.Split(secretConfig.Target, \"/\")\n\t\tlastPart := pathSplitted[len(pathSplitted)-1]\n\n\t\t// if the filename (lastPart) and the target is the same\n\t\tif lastPart == secretConfig.Target {\n\t\t\t// the secret path should be the source (it need to be inside a directory and only the filename was given)\n\t\t\tmountPath = secretConfig.Source\n\t\t} else {\n\t\t\t// should then get the target without the filename (lastPart)\n\t\t\tmountPath = mountPath + strings.TrimSuffix(secretConfig.Target, \"/\"+lastPart) // menos ultima parte\n\t\t}\n\n\t\t// if the target isn't absolute path\n\t\tif !strings.HasPrefix(secretConfig.Target, \"/\") {\n\t\t\t// concat the default secret directory\n\t\t\tmountPath = \"/run/secrets/\" + mountPath\n\t\t}\n\n\t\titemPath = lastPart\n\t}\n\n\tsecretSubPath = itemPath //\"\" // We didn't set a SubPath in legacy behavior\n\treturn itemPath, mountPath, secretSubPath\n}\n\n// ConfigVolumes configure the container volumes.\nfunc (k *Kubernetes) ConfigVolumes(name string, service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume, []*api.PersistentVolumeClaim, []*api.ConfigMap, error) {\n\tvolumeMounts := []api.VolumeMount{}\n\tvolumes := []api.Volume{}\n\tvar PVCs []*api.PersistentVolumeClaim\n\tvar cms []*api.ConfigMap\n\tvar volumeName string\n\tvar subpathName string\n\n\t// Set a var based on if the user wants to use empty volumes\n\t// as opposed to persistent volumes and volume claims\n\tuseEmptyVolumes := k.Opt.EmptyVols\n\tuseHostPath := k.Opt.Volumes == \"hostPath\"\n\tuseConfigMap := k.Opt.Volumes == \"configMap\"\n\tif k.Opt.Volumes == \"emptyDir\" {\n\t\tuseEmptyVolumes = true\n\t}\n\n\tif subpath, ok := service.Labels[\"kompose.volume.subpath\"]; ok {\n\t\tsubpathName = subpath\n\t}\n\n\t// Override volume type if specified in service labels.\n\tif vt, ok := service.Labels[\"kompose.volume.type\"]; ok {\n\t\tif _, okk := ValidVolumeSet[vt]; !okk {\n\t\t\treturn nil, nil, nil, nil, fmt.Errorf(\"invalid volume type %s specified in label 'kompose.volume.type' in service %s\", vt, service.Name)\n\t\t}\n\t\tuseEmptyVolumes = vt == \"emptyDir\"\n\t\tuseHostPath = vt == \"hostPath\"\n\t\tuseConfigMap = vt == \"configMap\"\n\t}\n\n\t// config volumes from secret if present\n\tsecretsVolumeMounts, secretsVolumes := k.ConfigSecretVolumes(name, service)\n\tvolumeMounts = append(volumeMounts, secretsVolumeMounts...)\n\tvolumes = append(volumes, secretsVolumes...)\n\n\tvar count int\n\tskip := false\n\t//iterating over array of `Vols` struct as it contains all necessary information about volumes\n\tfor _, volume := range service.Volumes {\n\t\t// check if ro/rw mode is defined, default rw\n\t\treadonly := len(volume.Mode) > 0 && (volume.Mode == \"ro\" || volume.Mode == \"rox\")\n\t\tmountHost := volume.Host\n\t\tif mountHost == \"\" {\n\t\t\tmountHost = volume.MountPath\n\t\t}\n\t\t// return useconfigmap and readonly,\n\t\t// not used asigned readonly because dont break e2e\n\t\tuseConfigMap, _, skip = isConfigFile(mountHost)\n\t\tif skip {\n\t\t\tlog.Warnf(\"Skip file in path %s \", volume.Host)\n\t\t\tcontinue\n\t\t}\n\t\tif volume.VolumeName == \"\" {\n\t\t\tif useEmptyVolumes {\n\t\t\t\tvolumeName = strings.Replace(volume.PVCName, \"claim\", \"empty\", 1)\n\t\t\t} else if useHostPath {\n\t\t\t\tvolumeName = strings.Replace(volume.PVCName, \"claim\", \"hostpath\", 1)\n\t\t\t} else if useConfigMap {\n\t\t\t\tvolumeName = strings.Replace(volume.PVCName, \"claim\", \"cm\", 1)\n\t\t\t} else {\n\t\t\t\tvolumeName = volume.PVCName\n\t\t\t}\n\t\t\t// to support service group bases on volume, we need use the new group name to replace the origin service name\n\t\t\t// in volume name. For normal service, this should have no effect\n\t\t\tvolumeName = strings.Replace(volumeName, service.Name, name, 1)\n\t\t\tcount++\n\t\t} else {\n\t\t\tvolumeName = volume.VolumeName\n\t\t}\n\t\tvolMount := api.VolumeMount{\n\t\t\tName:      volumeName,\n\t\t\tReadOnly:  readonly,\n\t\t\tMountPath: volume.Container,\n\t\t}\n\n\t\t// Get a volume source based on the type of volume we are using\n\t\t// For PVC we will also create a PVC object and add to list\n\t\tvar volsource *api.VolumeSource\n\n\t\tif useEmptyVolumes {\n\t\t\tvolsource = k.ConfigEmptyVolumeSource(\"volume\")\n\t\t} else if useHostPath {\n\t\t\tsource, err := k.ConfigHostPathVolumeSource(volume.Host)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, nil, nil, errors.Wrap(err, \"k.ConfigHostPathVolumeSource failed\")\n\t\t\t}\n\t\t\tvolsource = source\n\t\t} else if useConfigMap {\n\t\t\tlog.Debugf(\"Use configmap volume\")\n\t\t\tcm, err := k.IntiConfigMapFromFileOrDir(name, volumeName, volume.Host, service)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, nil, nil, err\n\t\t\t}\n\t\t\tcms = append(cms, cm)\n\t\t\tvolsource = k.ConfigConfigMapVolumeSource(volumeName, volume.Container, cm)\n\n\t\t\tif useSubPathMount(cm) {\n\t\t\t\tvolMount.SubPath = volsource.ConfigMap.Items[0].Path\n\t\t\t}\n\t\t} else {\n\t\t\tvolsource = k.ConfigPVCVolumeSource(volumeName, readonly)\n\t\t\tif volume.VFrom == \"\" {\n\t\t\t\tvar storageClassName string\n\t\t\t\tdefaultSize := PVCRequestSize\n\t\t\t\tif k.Opt.PVCRequestSize != \"\" {\n\t\t\t\t\tdefaultSize = k.Opt.PVCRequestSize\n\t\t\t\t}\n\t\t\t\tif len(volume.PVCSize) > 0 {\n\t\t\t\t\tdefaultSize = volume.PVCSize\n\t\t\t\t} else {\n\t\t\t\t\tfor key, value := range service.Labels {\n\t\t\t\t\t\tif key == \"kompose.volume.size\" {\n\t\t\t\t\t\t\tdefaultSize = value\n\t\t\t\t\t\t} else if key == \"kompose.volume.storage-class-name\" {\n\t\t\t\t\t\t\tstorageClassName = value\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcreatedPVC, err := k.CreatePVC(volumeName, volume.Mode, defaultSize, volume.SelectorValue, storageClassName)\n\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, nil, nil, errors.Wrap(err, \"k.CreatePVC failed\")\n\t\t\t\t}\n\n\t\t\t\tPVCs = append(PVCs, createdPVC)\n\t\t\t}\n\t\t}\n\t\tif subpathName != \"\" {\n\t\t\tvolMount.SubPath = subpathName\n\t\t}\n\t\tvolumeMounts = append(volumeMounts, volMount)\n\n\t\t// create a new volume object using the volsource and add to list\n\t\tvol := api.Volume{\n\t\t\tName:         volumeName,\n\t\t\tVolumeSource: *volsource,\n\t\t}\n\t\tvolumes = append(volumes, vol)\n\n\t\tif len(volume.Host) > 0 && (!useHostPath && !useConfigMap) {\n\t\t\tlog.Warningf(\"Volume mount on the host %q isn't supported - ignoring path on the host\", volume.Host)\n\t\t}\n\t}\n\n\treturn volumeMounts, volumes, PVCs, cms, nil\n}\n\n// ConfigEmptyVolumeSource is helper function to create an EmptyDir api.VolumeSource\n// either for Tmpfs or for emptyvolumes\nfunc (k *Kubernetes) ConfigEmptyVolumeSource(key string) *api.VolumeSource {\n\t//if key is tmpfs\n\tif key == \"tmpfs\" {\n\t\treturn &api.VolumeSource{\n\t\t\tEmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory},\n\t\t}\n\t}\n\n\t//if key is volume\n\treturn &api.VolumeSource{\n\t\tEmptyDir: &api.EmptyDirVolumeSource{},\n\t}\n}\n\n// ConfigConfigMapVolumeSource config a configmap to use as volume source\nfunc (k *Kubernetes) ConfigConfigMapVolumeSource(cmName string, targetPath string, cm *api.ConfigMap) *api.VolumeSource {\n\ts := api.ConfigMapVolumeSource{}\n\ts.Name = cmName\n\tif useSubPathMount(cm) {\n\t\tvar keys []string\n\t\tfor k := range cm.Data {\n\t\t\tkeys = append(keys, k)\n\t\t}\n\t\tfor k := range cm.BinaryData {\n\t\t\tkeys = append(keys, k)\n\t\t}\n\t\tkey := keys[0]\n\t\t_, p := path.Split(targetPath)\n\t\ts.Items = []api.KeyToPath{\n\t\t\t{\n\t\t\t\tKey:  key,\n\t\t\t\tPath: p,\n\t\t\t},\n\t\t}\n\t}\n\treturn &api.VolumeSource{\n\t\tConfigMap: &s,\n\t}\n}\n\n// ConfigHostPathVolumeSource is a helper function to create a HostPath api.VolumeSource\nfunc (k *Kubernetes) ConfigHostPathVolumeSource(path string) (*api.VolumeSource, error) {\n\tdir, err := transformer.GetComposeFileDir(k.Opt.InputFiles)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tabsPath := path\n\tif !filepath.IsAbs(path) {\n\t\tabsPath = filepath.Join(dir, path)\n\t}\n\n\treturn &api.VolumeSource{\n\t\tHostPath: &api.HostPathVolumeSource{Path: absPath},\n\t}, nil\n}\n\n// ConfigPVCVolumeSource is helper function to create an api.VolumeSource with a PVC\nfunc (k *Kubernetes) ConfigPVCVolumeSource(name string, readonly bool) *api.VolumeSource {\n\treturn &api.VolumeSource{\n\t\tPersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{\n\t\t\tClaimName: name,\n\t\t\tReadOnly:  readonly,\n\t\t},\n\t}\n}\n\n// ConfigEnvs configures the environment variables.\nfunc ConfigEnvs(service kobject.ServiceConfig, opt kobject.ConvertOptions) ([]api.EnvVar, []api.EnvFromSource, error) {\n\tenvs := transformer.EnvSort{}\n\tenvsFrom := []api.EnvFromSource{}\n\n\tkeysFromEnvFile := make(map[string]bool)\n\t// If there is an env_file, use ConfigMaps and add them using EnvFrom\n\n\tif len(service.EnvFile) > 0 {\n\t\t// Load each env_file\n\t\tfor _, file := range service.EnvFile {\n\t\t\tenvName := FormatEnvName(file, service.Name)\n\n\t\t\tenvsFrom = append(envsFrom, api.EnvFromSource{\n\t\t\t\tConfigMapRef: &api.ConfigMapEnvSource{\n\t\t\t\t\tLocalObjectReference: api.LocalObjectReference{\n\t\t\t\t\t\tName: envName,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})\n\n\t\t\t// Load environment variables from file\n\t\t\tworkDir, err := transformer.GetComposeFileDir(opt.InputFiles)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"Unable to get compose file directory: %s\", err)\n\t\t\t}\n\t\t\tenvLoad, err := GetEnvsFromFile(filepath.Join(workDir, file))\n\t\t\tif err != nil {\n\t\t\t\treturn envs, envsFrom, errors.Wrap(err, \"Unable to read env_file\")\n\t\t\t}\n\n\t\t\t// Mark environment variable source to env file\n\t\t\tfor k := range envLoad {\n\t\t\t\tkeysFromEnvFile[k] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Load up the environment variables\n\tfor _, v := range service.Environment {\n\t\tif !keysFromEnvFile[v.Name] {\n\t\t\tif strings.Contains(v.Value, \"run/secrets\") {\n\t\t\t\tv.Value = FormatResourceName(v.Value)\n\t\t\t}\n\t\t\tenvs = append(envs, api.EnvVar{\n\t\t\t\tName:  v.Name,\n\t\t\t\tValue: v.Value,\n\t\t\t})\n\t\t}\n\t}\n\n\t// Stable sorts data while keeping the original order of equal elements\n\t// we need this because envs are not populated in any random order\n\t// this sorting ensures they are populated in a particular order\n\tsort.Stable(envs)\n\treturn envs, envsFrom, nil\n}\n\n// ConfigAffinity configures the Affinity.\nfunc ConfigAffinity(service kobject.ServiceConfig) *api.Affinity {\n\tvar affinity *api.Affinity\n\t// Config constraints\n\t// Convert constraints to requiredDuringSchedulingIgnoredDuringExecution\n\tpositiveConstraints := configConstrains(service.Placement.PositiveConstraints, api.NodeSelectorOpIn)\n\tnegativeConstraints := configConstrains(service.Placement.NegativeConstraints, api.NodeSelectorOpNotIn)\n\tif len(positiveConstraints) != 0 || len(negativeConstraints) != 0 {\n\t\taffinity = &api.Affinity{\n\t\t\tNodeAffinity: &api.NodeAffinity{\n\t\t\t\tRequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{\n\t\t\t\t\tNodeSelectorTerms: []api.NodeSelectorTerm{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMatchExpressions: append(positiveConstraints, negativeConstraints...),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\treturn affinity\n}\n\n// ConfigTopologySpreadConstraints configures the TopologySpreadConstraints.\nfunc ConfigTopologySpreadConstraints(service kobject.ServiceConfig) []api.TopologySpreadConstraint {\n\tpreferencesLen := len(service.Placement.Preferences)\n\tconstraints := make([]api.TopologySpreadConstraint, 0, preferencesLen)\n\n\t// Placement preferences are ignored for global services\n\tif service.DeployMode == \"global\" {\n\t\tlog.Warnf(\"Ignore placement preferences for global service %s\", service.Name)\n\t\treturn constraints\n\t}\n\n\tfor i, p := range service.Placement.Preferences {\n\t\tconstraints = append(constraints, api.TopologySpreadConstraint{\n\t\t\t// According to the order of preferences, the MaxSkew decreases in order\n\t\t\t// The minimum value is 1\n\t\t\tMaxSkew:           int32(preferencesLen - i),\n\t\t\tTopologyKey:       p,\n\t\t\tWhenUnsatisfiable: api.ScheduleAnyway,\n\t\t\tLabelSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: transformer.ConfigLabels(service.Name),\n\t\t\t},\n\t\t})\n\t}\n\n\treturn constraints\n}\n\nfunc configConstrains(constrains map[string]string, operator api.NodeSelectorOperator) []api.NodeSelectorRequirement {\n\tconstraintsLen := len(constrains)\n\trs := make([]api.NodeSelectorRequirement, 0, constraintsLen)\n\tif constraintsLen == 0 {\n\t\treturn rs\n\t}\n\tfor k, v := range constrains {\n\t\tr := api.NodeSelectorRequirement{\n\t\t\tKey:      k,\n\t\t\tOperator: operator,\n\t\t\tValues:   []string{v},\n\t\t}\n\t\trs = append(rs, r)\n\t}\n\treturn rs\n}\n\n// CreateWorkloadAndConfigMapObjects generates a Kubernetes artifact for each input type service\nfunc (k *Kubernetes) CreateWorkloadAndConfigMapObjects(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions) []runtime.Object {\n\tvar objects []runtime.Object\n\tvar replica int\n\n\tif opt.IsReplicaSetFlag || service.Replicas == 0 {\n\t\treplica = opt.Replicas\n\t} else {\n\t\treplica = service.Replicas\n\t}\n\n\t// Check to see if Compose v3 Deploy.Mode has been set to \"global\"\n\tif service.DeployMode == \"global\" {\n\t\t//default use daemonset\n\t\tif opt.Controller == \"\" {\n\t\t\topt.CreateD = false\n\t\t\topt.CreateDS = true\n\t\t} else if opt.Controller != \"daemonset\" {\n\t\t\tlog.Warnf(\"Global deploy mode service is best converted to daemonset, now it convert to %s\", opt.Controller)\n\t\t}\n\t}\n\n\t//Resolve labels first\n\tif val, ok := service.Labels[compose.LabelControllerType]; ok {\n\t\topt.CreateD = false\n\t\topt.CreateDS = false\n\t\topt.CreateRC = false\n\t\tif opt.Controller != \"\" {\n\t\t\tlog.Warnf(\"Use label %s type %s for service %s, ignore %s flags\", compose.LabelControllerType, val, name, opt.Controller)\n\t\t}\n\t\topt.Controller = val\n\t}\n\n\tif len(service.Configs) > 0 {\n\t\tobjects = k.createConfigMapFromComposeConfig(name, service, objects)\n\t}\n\n\tif opt.CreateD || opt.Controller == DeploymentController {\n\t\tobjects = append(objects, k.InitD(name, service, replica))\n\t}\n\n\tif opt.CreateDS || opt.Controller == DaemonSetController {\n\t\tobjects = append(objects, k.InitDS(name, service))\n\t}\n\n\tif opt.Controller == StatefulStateController {\n\t\tobjects = append(objects, k.InitSS(name, service, replica))\n\t}\n\n\tenvConfigMaps := k.PargeEnvFiletoConfigMaps(name, service, opt)\n\tobjects = append(objects, envConfigMaps...)\n\treturn objects\n}\n\nfunc (k *Kubernetes) createConfigMapFromComposeConfig(name string, service kobject.ServiceConfig, objects []runtime.Object) []runtime.Object {\n\tfor _, config := range service.Configs {\n\t\tcurrentConfigName := config.Source\n\t\tcurrentConfigObj := service.ConfigsMetaData[currentConfigName]\n\t\tif config.Target == \"\" {\n\t\t\tconfig.Target = currentConfigName\n\t\t}\n\t\tif currentConfigObj.External {\n\t\t\tcontinue\n\t\t}\n\t\tif currentConfigObj.File != \"\" {\n\t\t\tcurrentFileName := currentConfigObj.File\n\t\t\tconfigMap := k.InitConfigMapFromFile(name, service, currentFileName)\n\t\t\tobjects = append(objects, configMap)\n\t\t} else if currentConfigObj.Content != \"\" {\n\t\t\tcontent := currentConfigObj.Content\n\t\t\tconfigMap := k.InitConfigMapFromContent(name, service, content, currentConfigName, config.Target)\n\t\t\tobjects = append(objects, configMap)\n\t\t} else if currentConfigObj.Environment != \"\" {\n\t\t\t// TODO: Add support for environment variables in configmaps\n\t\t\tlog.Warnf(\"Environment variables in configmaps are not supported yet\")\n\t\t} else {\n\t\t\tlog.Warnf(\"Configmap %s is empty\", currentConfigName)\n\t\t}\n\t}\n\treturn objects\n}\n\n// InitPod initializes Kubernetes Pod object\nfunc (k *Kubernetes) InitPod(name string, service kobject.ServiceConfig) *api.Pod {\n\tpod := api.Pod{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"Pod\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:        name,\n\t\t\tLabels:      transformer.ConfigLabels(name),\n\t\t\tAnnotations: transformer.ConfigAnnotations(service),\n\t\t},\n\t\tSpec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),\n\t}\n\treturn &pod\n}\n\n// CreateNetworkPolicy initializes Network policy\nfunc (k *Kubernetes) CreateNetworkPolicy(networkName string) (*networkingv1.NetworkPolicy, error) {\n\tstr := \"true\"\n\tnp := &networkingv1.NetworkPolicy{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"NetworkPolicy\",\n\t\t\tAPIVersion: \"networking.k8s.io/v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: networkName,\n\t\t\t//Labels: transformer.ConfigLabels(name)(name),\n\t\t},\n\t\tSpec: networkingv1.NetworkPolicySpec{\n\t\t\tPodSelector: metav1.LabelSelector{\n\t\t\t\tMatchLabels: map[string]string{\"io.kompose.network/\" + networkName: str},\n\t\t\t},\n\t\t\tIngress: []networkingv1.NetworkPolicyIngressRule{{\n\t\t\t\tFrom: []networkingv1.NetworkPolicyPeer{{\n\t\t\t\t\tPodSelector: &metav1.LabelSelector{\n\t\t\t\t\t\tMatchLabels: map[string]string{\"io.kompose.network/\" + networkName: str},\n\t\t\t\t\t},\n\t\t\t\t}},\n\t\t\t}},\n\t\t},\n\t}\n\n\treturn np, nil\n}\n\nfunc buildServiceImage(opt kobject.ConvertOptions, service kobject.ServiceConfig, name string) error {\n\t// Must build the images before conversion (got to add service.Image in case 'image' key isn't provided\n\t// Check that --build is set to true\n\t// Check to see if there is an InputFile (required!) before we build the container\n\t// Check that there's actually a Build key\n\t// Lastly, we must have an Image name to continue\n\n\t// If the user provided a custom build it will override the docker one.\n\tif opt.BuildCommand != \"\" && opt.PushCommand != \"\" {\n\t\tp := shellwords.NewParser()\n\t\tp.ParseEnv = true\n\n\t\tbuildArgs, _ := p.Parse(opt.BuildCommand)\n\t\tbuildCommand := exec.Command(buildArgs[0], buildArgs[1:]...)\n\t\terr := buildCommand.Run()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"error while trying to build a custom container image\")\n\t\t}\n\n\t\tpushArgs, _ := p.Parse(opt.PushCommand)\n\t\tpushCommand := exec.Command(pushArgs[0], pushArgs[1:]...)\n\t\terr = pushCommand.Run()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"error while trying to push a custom container image\")\n\t\t}\n\t\treturn nil\n\t}\n\tif opt.Build == \"local\" && opt.InputFiles != nil && service.Build != \"\" {\n\t\t// If there's no \"image\" key, use the name of the container that's built\n\t\tif service.Image == \"\" {\n\t\t\tservice.Image = name\n\t\t}\n\n\t\tif service.Image == \"\" {\n\t\t\treturn fmt.Errorf(\"image key required within build parameters in order to build and push service '%s'\", name)\n\t\t}\n\n\t\tlog.Infof(\"Build key detected. Attempting to build image '%s'\", service.Image)\n\n\t\t// Build the image!\n\t\terr := transformer.BuildDockerImage(service, name)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"Unable to build Docker image for service %v\", name)\n\t\t}\n\n\t\t// Push the built image to the repo!\n\t\terr = transformer.PushDockerImageWithOpt(service, name, opt)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"Unable to push Docker image for service %v\", name)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (k *Kubernetes) configKubeServiceAndIngressForService(service kobject.ServiceConfig, name string, objects *[]runtime.Object) {\n\tif k.PortsExist(service) {\n\t\tif service.ServiceType == \"LoadBalancer\" {\n\t\t\tsvcs := k.CreateLBService(name, service)\n\t\t\tfor _, svc := range svcs {\n\t\t\t\tsvc.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyType(service.ServiceExternalTrafficPolicy)\n\t\t\t\t*objects = append(*objects, svc)\n\t\t\t}\n\t\t\tif len(svcs) > 1 {\n\t\t\t\tlog.Warningf(\"Create multiple service to avoid using mixed protocol in the same service when it's loadbalancer type\")\n\t\t\t}\n\t\t} else {\n\t\t\tsvc := k.CreateService(name, service)\n\t\t\t*objects = append(*objects, svc)\n\t\t\tif service.ExposeService != \"\" {\n\t\t\t\t*objects = append(*objects, k.initIngress(name, service, svc.Spec.Ports[0].Port))\n\t\t\t}\n\t\t\tif service.ServiceExternalTrafficPolicy != \"\" && svc.Spec.Type != api.ServiceTypeNodePort {\n\t\t\t\tlog.Warningf(\"External Traffic Policy is ignored for the service %v of type %v\", name, service.ServiceType)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif service.ServiceType == \"Headless\" {\n\t\t\tsvc := k.CreateHeadlessService(name, service)\n\t\t\t*objects = append(*objects, svc)\n\t\t\tif service.ServiceExternalTrafficPolicy != \"\" {\n\t\t\t\tlog.Warningf(\"External Traffic Policy is ignored for the service %v of type Headless\", name)\n\t\t\t}\n\t\t} else {\n\t\t\tlog.Warnf(\"Service %q won't be created because 'ports' is not specified\", service.Name)\n\t\t}\n\t}\n}\n\nfunc (k *Kubernetes) configNetworkPolicyForService(service kobject.ServiceConfig, name string, objects *[]runtime.Object) error {\n\tif len(service.Network) > 0 {\n\t\tfor _, net := range service.Network {\n\t\t\tlog.Infof(\"Network %s is detected at Source, shall be converted to equivalent NetworkPolicy at Destination\", net)\n\t\t\tnp, err := k.CreateNetworkPolicy(net)\n\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"Unable to create Network Policy for network %v for service %v\", net, name)\n\t\t\t}\n\t\t\t*objects = append(*objects, np)\n\t\t}\n\t}\n\treturn nil\n}\n\n// Transform maps komposeObject to k8s objects\n// returns object that are already sorted in the way that Services are first\nfunc (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) ([]runtime.Object, error) {\n\t// this will hold all the converted data\n\tvar allobjects []runtime.Object\n\n\tif komposeObject.Secrets != nil {\n\t\tsecrets, err := k.CreateSecrets(komposeObject)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"Unable to create Secret resource\")\n\t\t}\n\t\tfor _, item := range secrets {\n\t\t\tallobjects = append(allobjects, item)\n\t\t}\n\t}\n\n\tif komposeObject.Namespace != \"\" {\n\t\tns := transformer.CreateNamespace(komposeObject.Namespace)\n\t\tallobjects = append(allobjects, ns)\n\t}\n\n\tif opt.ServiceGroupMode != \"\" {\n\t\tlog.Debugf(\"Service group mode is: %s\", opt.ServiceGroupMode)\n\t\tkomposeObjectToServiceConfigGroupMapping := KomposeObjectToServiceConfigGroupMapping(&komposeObject, opt)\n\t\tsortedGroupMappingKeys := SortedKeys(komposeObjectToServiceConfigGroupMapping)\n\t\tfor _, group := range sortedGroupMappingKeys {\n\t\t\tgroupMapping := komposeObjectToServiceConfigGroupMapping[group]\n\t\t\tvar objects []runtime.Object\n\t\t\tpodSpec := PodSpec{}\n\n\t\t\tvar groupName string\n\t\t\t// if using volume group, the name here will be a volume config string. reset to the first service name\n\t\t\tif opt.ServiceGroupMode == \"volume\" {\n\t\t\t\tif opt.ServiceGroupName != \"\" {\n\t\t\t\t\tgroupName = opt.ServiceGroupName\n\t\t\t\t} else {\n\t\t\t\t\tvar names []string\n\t\t\t\t\tfor _, svc := range groupMapping {\n\t\t\t\t\t\tnames = append(names, svc.Name)\n\t\t\t\t\t}\n\t\t\t\t\tgroupName = strings.Join(names, \"-\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tgroupName = group\n\t\t\t}\n\n\t\t\t// added a container\n\t\t\t// ports conflict check between services\n\t\t\tportsUses := map[string]bool{}\n\n\t\t\tfor _, service := range groupMapping {\n\t\t\t\t// first do ports check\n\t\t\t\tports := ConfigPorts(service)\n\t\t\t\tfor _, port := range ports {\n\t\t\t\t\tkey := string(port.ContainerPort) + string(port.Protocol)\n\t\t\t\t\tif portsUses[key] {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"detect ports conflict when group services, service: %s, port: %d\", service.Name, port.ContainerPort)\n\t\t\t\t\t}\n\t\t\t\t\tportsUses[key] = true\n\t\t\t\t}\n\n\t\t\t\tlog.Infof(\"Group Service %s to [%s]\", service.Name, groupName)\n\t\t\t\tservice.WithKomposeAnnotation = opt.WithKomposeAnnotation\n\t\t\t\tpodSpec.Append(AddContainer(service, opt))\n\n\t\t\t\tif err := buildServiceImage(opt, service, service.Name); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\t// override..\n\t\t\t\tobjects = append(objects, k.CreateWorkloadAndConfigMapObjects(groupName, service, opt)...)\n\t\t\t\tk.configKubeServiceAndIngressForService(service, groupName, &objects)\n\n\t\t\t\t// Configure the container volumes.\n\t\t\t\tvolumesMount, volumes, pvc, cms, err := k.ConfigVolumes(groupName, service)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, errors.Wrap(err, \"k.ConfigVolumes failed\")\n\t\t\t\t}\n\t\t\t\t// Configure Tmpfs\n\t\t\t\tif len(service.TmpFs) > 0 {\n\t\t\t\t\tTmpVolumesMount, TmpVolumes := k.ConfigTmpfs(groupName, service)\n\t\t\t\t\tvolumes = append(volumes, TmpVolumes...)\n\t\t\t\t\tvolumesMount = append(volumesMount, TmpVolumesMount...)\n\t\t\t\t}\n\t\t\t\tpodSpec.Append(\n\t\t\t\t\tSetVolumeMounts(volumesMount),\n\t\t\t\t\tSetVolumes(volumes),\n\t\t\t\t)\n\n\t\t\t\t// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`\n\t\t\t\t// because the type of objects and pvc is different, but when doing append\n\t\t\t\t// one element at a time it gets converted to runtime.Object for objects slice\n\t\t\t\tfor _, p := range pvc {\n\t\t\t\t\tobjects = append(objects, p)\n\t\t\t\t}\n\n\t\t\t\tfor _, c := range cms {\n\t\t\t\t\tobjects = append(objects, c)\n\t\t\t\t}\n\n\t\t\t\tpodSpec.Append(\n\t\t\t\t\tSetPorts(service),\n\t\t\t\t\tImagePullPolicy(groupName, service),\n\t\t\t\t\tRestartPolicy(groupName, service),\n\t\t\t\t\tSecurityContext(groupName, service),\n\t\t\t\t\tHostName(service),\n\t\t\t\t\tDomainName(service),\n\t\t\t\t\tResourcesLimits(service),\n\t\t\t\t\tResourcesRequests(service),\n\t\t\t\t\tTerminationGracePeriodSeconds(groupName, service),\n\t\t\t\t\tTopologySpreadConstraints(service),\n\t\t\t\t)\n\n\t\t\t\tif serviceAccountName, ok := service.Labels[compose.LabelServiceAccountName]; ok {\n\t\t\t\t\tpodSpec.Append(ServiceAccountName(serviceAccountName))\n\t\t\t\t}\n\n\t\t\t\terr = k.UpdateKubernetesObjectsMultipleContainers(groupName, service, &objects, podSpec, opt)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, errors.Wrap(err, \"Error transforming Kubernetes objects\")\n\t\t\t\t}\n\n\t\t\t\tif opt.GenerateNetworkPolicies {\n\t\t\t\t\tif err = k.configNetworkPolicyForService(service, service.Name, &objects); err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tallobjects = append(allobjects, objects...)\n\t\t}\n\t}\n\tsortedKeys := SortedKeys(komposeObject.ServiceConfigs)\n\tfor _, name := range sortedKeys {\n\t\tservice := komposeObject.ServiceConfigs[name]\n\n\t\t// if service belongs to a group, we already processed it\n\t\tif service.InGroup {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar objects []runtime.Object\n\n\t\tservice.WithKomposeAnnotation = opt.WithKomposeAnnotation\n\n\t\tif err := buildServiceImage(opt, service, name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Generate pod or cronjob and configmap objects\n\t\tif (service.Restart == \"no\" || service.Restart == \"on-failure\") && !opt.IsPodController() {\n\t\t\tif service.CronJobSchedule != \"\" {\n\t\t\t\tlog.Infof(\"Create kubernetes pod instead of pod controller due to restart policy: %s\", service.Restart)\n\t\t\t\tcronJob := k.InitCJ(name, service, service.CronJobSchedule, service.CronJobConcurrencyPolicy, service.CronJobBackoffLimit)\n\t\t\t\tobjects = append(objects, cronJob)\n\t\t\t} else {\n\t\t\t\tpod := k.InitPod(name, service)\n\t\t\t\tobjects = append(objects, pod)\n\t\t\t}\n\t\t\tenvConfigMaps := k.PargeEnvFiletoConfigMaps(name, service, opt)\n\t\t\tobjects = append(objects, envConfigMaps...)\n\t\t} else {\n\t\t\tobjects = k.CreateWorkloadAndConfigMapObjects(name, service, opt)\n\t\t}\n\t\tif opt.Controller == StatefulStateController {\n\t\t\tservice.ServiceType = \"Headless\"\n\t\t}\n\t\tk.configKubeServiceAndIngressForService(service, name, &objects)\n\t\terr := k.UpdateKubernetesObjects(name, service, opt, &objects)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Error transforming Kubernetes objects\")\n\t\t}\n\t\tif opt.GenerateNetworkPolicies {\n\t\t\tif err := k.configNetworkPolicyForService(service, name, &objects); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\terr = k.configHorizontalPodScaler(name, service, opt, &objects)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Error creating Kubernetes HPA\")\n\t\t}\n\t\tallobjects = append(allobjects, objects...)\n\t}\n\n\t// sort all object so Services are first\n\tk.SortServicesFirst(&allobjects)\n\tk.RemoveDupObjects(&allobjects)\n\n\t// Only append namespaces if --namespace has been passed in\n\tif komposeObject.Namespace != \"\" {\n\t\ttransformer.AssignNamespaceToObjects(&allobjects, komposeObject.Namespace)\n\t}\n\t// k.FixWorkloadVersion(&allobjects)\n\tk.fixNetworkModeToService(&allobjects, komposeObject.ServiceConfigs)\n\treturn allobjects, nil\n}\n\n// UpdateController updates the given object with the given pod template update function and ObjectMeta update function\nfunc (k *Kubernetes) UpdateController(obj runtime.Object, updateTemplate func(*api.PodTemplateSpec) error, updateMeta func(meta *metav1.ObjectMeta)) (err error) {\n\tswitch t := obj.(type) {\n\tcase *appsv1.Deployment:\n\t\terr = updateTemplate(&t.Spec.Template)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"updateTemplate failed\")\n\t\t}\n\t\tupdateMeta(&t.ObjectMeta)\n\tcase *appsv1.DaemonSet:\n\t\terr = updateTemplate(&t.Spec.Template)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"updateTemplate failed\")\n\t\t}\n\t\tupdateMeta(&t.ObjectMeta)\n\tcase *appsv1.StatefulSet:\n\t\terr = updateTemplate(&t.Spec.Template)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"updateTemplate failed\")\n\t\t}\n\t\tupdateMeta(&t.ObjectMeta)\n\tcase *batchv1.CronJob:\n\t\terr = updateTemplate(&t.Spec.JobTemplate.Spec.Template)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"updateTemplate failed\")\n\t\t}\n\t\tupdateMeta(&t.ObjectMeta)\n\tcase *deployapi.DeploymentConfig:\n\t\terr = updateTemplate(t.Spec.Template)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"updateTemplate failed\")\n\t\t}\n\t\tupdateMeta(&t.ObjectMeta)\n\tcase *api.Pod:\n\t\tp := api.PodTemplateSpec{\n\t\t\tObjectMeta: t.ObjectMeta,\n\t\t\tSpec:       t.Spec,\n\t\t}\n\t\terr = updateTemplate(&p)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"updateTemplate failed\")\n\t\t}\n\t\tt.Spec = p.Spec\n\t\tt.ObjectMeta = p.ObjectMeta\n\tcase *buildapi.BuildConfig:\n\t\tupdateMeta(&t.ObjectMeta)\n\t}\n\treturn nil\n}\n\n// configHorizontalPodScaler create Hpa resource also append to the objects\n// first checks if the service labels contain any HPA labels using the searchHPAValues\nfunc (k *Kubernetes) configHorizontalPodScaler(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions, objects *[]runtime.Object) (err error) {\n\tfound := searchHPAValues(service.Labels)\n\tif !found {\n\t\treturn nil\n\t}\n\n\thpa := createHPAResources(name, &service)\n\t*objects = append(*objects, &hpa)\n\treturn nil\n}\n\nfunc (k *Kubernetes) PargeEnvFiletoConfigMaps(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions) []runtime.Object {\n\tenvs := make(map[string]string)\n\tfor _, env := range service.Environment {\n\t\tenvs[env.Name] = env.Value\n\t}\n\tconfigMaps := make([]runtime.Object, 0)\n\tfor _, envFile := range service.EnvFile {\n\t\tconfigMap := k.InitConfigMapForEnvWithLookup(name, opt, envFile, func(key string) (string, bool) {\n\t\t\tv, ok := envs[key]\n\t\t\treturn v, ok\n\t\t})\n\t\tconfigMaps = append(configMaps, configMap)\n\t}\n\treturn configMaps\n}\n"
  },
  {
    "path": "pkg/transformer/kubernetes/kubernetes_test.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage kubernetes\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/compose-spec/compose-go/v2/types\"\n\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/loader/compose\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\tdeployapi \"github.com/openshift/api/apps/v1\"\n\t\"github.com/pkg/errors\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tapi \"k8s.io/api/core/v1\"\n\tnetworkingv1 \"k8s.io/api/networking/v1\"\n\tnetworkingv1beta1 \"k8s.io/api/networking/v1beta1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n)\n\nfunc newServiceConfig() kobject.ServiceConfig {\n\treturn kobject.ServiceConfig{\n\t\tName:            \"app\",\n\t\tContainerName:   \"name\",\n\t\tImage:           \"image\",\n\t\tEnvironment:     []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:            []kobject.Ports{{HostPort: 123, ContainerPort: 456}, {HostPort: 123, ContainerPort: 456, Protocol: string(api.ProtocolUDP)}, {HostPort: 55564, ContainerPort: 55564}, {HostPort: 55563, ContainerPort: 55563}},\n\t\tCommand:         []string{\"cmd\"},\n\t\tWorkingDir:      \"dir\",\n\t\tArgs:            []string{\"arg1\", \"arg2\"},\n\t\tVolList:         []string{\"/tmp/volume\"},\n\t\tLabels:          nil,\n\t\tFsGroup:         1001,\n\t\tAnnotations:     map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:        1, // not supported\n\t\tCapAdd:          []string{\"cap_add\"},\n\t\tCapDrop:         []string{\"cap_drop\"},\n\t\tExpose:          []string{\"expose\"}, // not supported\n\t\tPrivileged:      true,\n\t\tRestart:         \"always\",\n\t\tImagePullSecret: \"regcred\",\n\t\tStdin:           true,\n\t\tTty:             true,\n\t\tTmpFs:           []string{\"/tmp\"},\n\t\tReplicas:        2,\n\t\tVolumes:         []kobject.Volumes{{SvcName: \"app\", MountPath: \"/tmp/volume\", PVCName: \"app-claim0\"}},\n\t\tGroupAdd:        []int64{1003, 1005},\n\t\tConfigs:         []types.ServiceConfigObjConfig{{Source: \"config\", Target: \"/etc/world\"}},\n\t\tConfigsMetaData: types.Configs{\"config\": types.ConfigObjConfig{Name: \"myconfig\", File: \"kubernetes_test.go\"}},\n\t}\n}\n\nfunc newSimpleServiceConfig() kobject.ServiceConfig {\n\treturn kobject.ServiceConfig{\n\t\tName:          \"app\",\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t}\n}\n\nfunc newKomposeObject() kobject.KomposeObject {\n\treturn kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfig()},\n\t}\n}\n\nfunc newKomposeObjectHostPortProtocolConfig() kobject.ServiceConfig {\n\treturn kobject.ServiceConfig{\n\t\tName:                  \"nginx\",\n\t\tContainerName:         \"nginx\",\n\t\tImage:                 \"nginx\",\n\t\tPort:                  []kobject.Ports{{HostPort: 80, Protocol: string(api.ProtocolTCP), ContainerPort: 80}},\n\t\tExposeContainerToHost: true,\n\t}\n}\n\nfunc newServiceConfigWithExternalTrafficPolicy() kobject.ServiceConfig {\n\tloadBalancerServiceType := string(api.ServiceTypeLoadBalancer)\n\treturn kobject.ServiceConfig{\n\t\tName:                         \"app\",\n\t\tPort:                         []kobject.Ports{{HostPort: 123, ContainerPort: 456}},\n\t\tServiceType:                  loadBalancerServiceType,\n\t\tServiceExternalTrafficPolicy: \"local\",\n\t}\n}\n\nfunc newServiceConfigWithServiceVolumeMount(volumeMountSubPathValue string) kobject.ServiceConfig {\n\treturn kobject.ServiceConfig{\n\t\tName:               \"app\",\n\t\tVolumeMountSubPath: volumeMountSubPathValue,\n\t}\n}\n\nfunc equalEnv(kobjectEnvs []kobject.EnvVar, k8sEnvs []api.EnvVar) bool {\n\tif len(kobjectEnvs) != len(k8sEnvs) {\n\t\treturn false\n\t}\n\tfor _, env := range kobjectEnvs {\n\t\tfound := false\n\t\tfor _, k8sEnv := range k8sEnvs {\n\t\t\tif env.Name == k8sEnv.Name && env.Value == k8sEnv.Value {\n\t\t\t\tfound = true\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc equalPorts(kobjectPorts []kobject.Ports, k8sPorts []api.ContainerPort) bool {\n\tif len(kobjectPorts) != len(k8sPorts) {\n\t\treturn false\n\t}\n\tfor _, port := range kobjectPorts {\n\t\tfound := false\n\t\tfor _, k8sPort := range k8sPorts {\n\t\t\t// FIXME: HostPort should be copied to container port\n\t\t\t//if port.HostPort == k8sPort.HostPort && port.Protocol == k8sPort.Protocol && port.ContainerPort == k8sPort.ContainerPort {\n\t\t\tif port.Protocol == string(k8sPort.Protocol) && port.ContainerPort == k8sPort.ContainerPort {\n\t\t\t\tfound = true\n\t\t\t}\n\t\t\t// Name and HostIp shouldn't be set\n\t\t\tif len(k8sPort.Name) != 0 || len(k8sPort.HostIP) != 0 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc equalStringMaps(map1 map[string]string, map2 map[string]string) bool {\n\tif len(map1) != len(map2) {\n\t\treturn false\n\t}\n\tfor k, v := range map1 {\n\t\tif map2[k] != v {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc checkPodTemplate(config kobject.ServiceConfig, template api.PodTemplateSpec, expectedLabels map[string]string) error {\n\tif len(template.Spec.Containers) == 0 {\n\t\treturn fmt.Errorf(\"Failed to set container: %#v vs. %#v\", config, template)\n\t}\n\tcontainer := template.Spec.Containers[0]\n\tif config.ContainerName != container.Name {\n\t\treturn fmt.Errorf(\"Found different container name: %v vs. %v\", config.ContainerName, container.Name)\n\t}\n\tif config.Image != container.Image {\n\t\treturn fmt.Errorf(\"Found different container image: %v vs. %v\", config.Image, container.Image)\n\t}\n\tif !equalEnv(config.Environment, container.Env) {\n\t\treturn fmt.Errorf(\"Found different container env: %#v vs. %#v\", config.Environment, container.Env)\n\t}\n\tif !equalPorts(config.Port, container.Ports) {\n\t\treturn fmt.Errorf(\"Found different container ports: %#v vs. %#v\", config.Port, container.Ports)\n\t}\n\tif !slices.Equal(config.Command, container.Command) {\n\t\treturn fmt.Errorf(\"Found different container cmd: %#v vs. %#v\", config.Command, container.Command)\n\t}\n\tif config.WorkingDir != container.WorkingDir {\n\t\treturn fmt.Errorf(\"Found different container WorkingDir: %#v vs. %#v\", config.WorkingDir, container.WorkingDir)\n\t}\n\tif !slices.Equal(config.Args, container.Args) {\n\t\treturn fmt.Errorf(\"Found different container args: %#v vs. %#v\", config.Args, container.Args)\n\t}\n\tif len(template.Spec.Volumes) == 0 || len(template.Spec.Volumes[0].Name) == 0 || template.Spec.Volumes[0].VolumeSource.PersistentVolumeClaim == nil && template.Spec.Volumes[0].ConfigMap == nil {\n\t\treturn fmt.Errorf(\"Found incorrect volumes: %v vs. %#v\", config.Volumes, template.Spec.Volumes)\n\t}\n\t// We only set controller labels here and k8s server will take care of other defaults, such as selectors\n\tif !equalStringMaps(expectedLabels, template.Labels) {\n\t\treturn fmt.Errorf(\"Found different template labels: %#v vs. %#v\", expectedLabels, template.Labels)\n\t}\n\trestartPolicyMapping := map[string]api.RestartPolicy{\"always\": api.RestartPolicyAlways}\n\tif restartPolicyMapping[config.Restart] != template.Spec.RestartPolicy {\n\t\treturn fmt.Errorf(\"Found incorrect restart policy: %v vs. %v\", config.Restart, template.Spec.RestartPolicy)\n\t}\n\tif config.Privileged == privilegedNilOrFalse(template) {\n\t\treturn fmt.Errorf(\"Found different template privileged: %#v vs. %#v\", config.Privileged, template.Spec.Containers[0].SecurityContext)\n\t}\n\tif config.FsGroup != *template.Spec.SecurityContext.FSGroup {\n\t\treturn fmt.Errorf(\"Found different pod security context fs group values: %#v vs. %#v\", config.FsGroup, *template.Spec.SecurityContext.FSGroup)\n\t}\n\tif config.Stdin != template.Spec.Containers[0].Stdin {\n\t\treturn fmt.Errorf(\"Found different values for stdin: %#v vs. %#v\", config.Stdin, template.Spec.Containers[0].Stdin)\n\t}\n\tif config.Tty != template.Spec.Containers[0].TTY {\n\t\treturn fmt.Errorf(\"Found different values for TTY: %#v vs. %#v\", config.Tty, template.Spec.Containers[0].TTY)\n\t}\n\tif config.ImagePullSecret != template.Spec.ImagePullSecrets[0].Name {\n\t\treturn fmt.Errorf(\"Found different values for ImagePullSecrets: %#v vs. %#v\", config.ImagePullSecret, template.Spec.ImagePullSecrets[0].Name)\n\t}\n\treturn nil\n}\n\nfunc privilegedNilOrFalse(template api.PodTemplateSpec) bool {\n\treturn len(template.Spec.Containers) == 0 || template.Spec.Containers[0].SecurityContext == nil ||\n\t\ttemplate.Spec.Containers[0].SecurityContext.Privileged == nil || !*template.Spec.Containers[0].SecurityContext.Privileged\n}\n\nfunc checkService(config kobject.ServiceConfig, svc *api.Service, expectedLabels map[string]string) error {\n\tif !equalStringMaps(expectedLabels, svc.Spec.Selector) {\n\t\treturn fmt.Errorf(\"Found unexpected selector: %#v vs. %#v\", expectedLabels, svc.Spec.Selector)\n\t}\n\tfor _, port := range svc.Spec.Ports {\n\t\tname := port.Name\n\t\texpectedName := strings.ToLower(name)\n\t\tif expectedName != name {\n\t\t\treturn fmt.Errorf(\"Found unexpected port name: %#v vs. %#v\", expectedName, name)\n\t\t}\n\t}\n\t// TODO: finish this\n\treturn nil\n}\n\nfunc checkMeta(config kobject.ServiceConfig, meta metav1.ObjectMeta, expectedName string, shouldSetLabels bool) error {\n\tif expectedName != meta.Name {\n\t\treturn fmt.Errorf(\"Found unexpected name: %s vs. %s\", expectedName, meta.Name)\n\t}\n\n\tif shouldSetLabels != (len(meta.Labels) > 0) {\n\t\treturn fmt.Errorf(\"Unexpected labels: %#v\", meta.Labels)\n\t}\n\treturn nil\n}\n\nfunc TestKomposeConvertIngress(t *testing.T) {\n\ttestCases := map[string]struct {\n\t\tkomposeObject kobject.KomposeObject\n\t\topt           kobject.ConvertOptions\n\t\tlabelValue    string\n\t}{\n\t\t\"Convert to Ingress: label set to true\":        {newKomposeObject(), kobject.ConvertOptions{CreateD: true}, \"true\"},\n\t\t\"Convert to Ingress: label set to example.com\": {newKomposeObject(), kobject.ConvertOptions{CreateD: true}, \"example.com\"},\n\t}\n\n\tfor name, test := range testCases {\n\t\tvar expectedHost string\n\n\t\tt.Log(\"Test case:\", name)\n\t\tk := Kubernetes{}\n\n\t\tappName := \"app\"\n\n\t\t// Setting value for ExposeService in ServiceConfig\n\t\tconfig := test.komposeObject.ServiceConfigs[appName]\n\t\tconfig.ExposeService = test.labelValue\n\t\ttest.komposeObject.ServiceConfigs[appName] = config\n\n\t\tswitch test.labelValue {\n\t\tcase \"true\":\n\t\t\texpectedHost = \"\"\n\t\tdefault:\n\t\t\texpectedHost = test.labelValue\n\t\t}\n\n\t\t// Run Transform\n\t\tobjs, err := k.Transform(test.komposeObject, test.opt)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\n\t\t// Check results\n\t\tfor _, obj := range objs {\n\t\t\tif ing, ok := obj.(*networkingv1beta1.Ingress); ok {\n\t\t\t\tif ing.ObjectMeta.Name != appName {\n\t\t\t\t\tt.Errorf(\"Expected ObjectMeta.Name to be %s, got %s instead\", appName, ing.ObjectMeta.Name)\n\t\t\t\t}\n\t\t\t\tif ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServiceName != appName {\n\t\t\t\t\tt.Errorf(\"Expected Backend.ServiceName to be %s, got %s instead\", appName, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServiceName)\n\t\t\t\t}\n\t\t\t\tif ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServicePort.IntVal != config.Port[0].HostPort {\n\t\t\t\t\tt.Errorf(\"Expected Backend.ServicePort to be %d, got %v instead\", config.Port[0].HostPort, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServicePort.IntVal)\n\t\t\t\t}\n\t\t\t\tif ing.Spec.Rules[0].Host != expectedHost {\n\t\t\t\t\tt.Errorf(\"Expected Rules[0].Host to be %s, got %s instead\", expectedHost, ing.Spec.Rules[0].Host)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestKomposeConvert(t *testing.T) {\n\treplicas := 3\n\ttestCases := map[string]struct {\n\t\tkomposeObject   kobject.KomposeObject\n\t\topt             kobject.ConvertOptions\n\t\texpectedNumObjs int\n\t}{\n\t\t// objects generated are deployment, service network policies (2) and pvc\n\t\t\"Convert to Deployments (D)\":                  {newKomposeObject(), kobject.ConvertOptions{CreateD: true, Replicas: replicas, IsReplicaSetFlag: true}, 4},\n\t\t\"Convert to Deployments (D) with v3 replicas\": {newKomposeObject(), kobject.ConvertOptions{CreateD: true}, 4},\n\t\t\"Convert to DaemonSets (DS)\":                  {newKomposeObject(), kobject.ConvertOptions{CreateDS: true}, 4},\n\t\t// objects generated are deployment, daemonset, ReplicationController, service and pvc\n\t\t\"Convert to D, DS, and RC\":                  {newKomposeObject(), kobject.ConvertOptions{CreateD: true, CreateDS: true, CreateRC: true, Replicas: replicas, IsReplicaSetFlag: true}, 5},\n\t\t\"Convert to D, DS, and RC with v3 replicas\": {newKomposeObject(), kobject.ConvertOptions{CreateD: true, CreateDS: true, CreateRC: true}, 5},\n\t\t// objects generated are statefulset\n\t\t\"Convert to SS with replicas \":   {newKomposeObject(), kobject.ConvertOptions{Controller: StatefulStateController, Replicas: replicas, IsReplicaSetFlag: true}, 3},\n\t\t\"Convert to SS without replicas\": {newKomposeObject(), kobject.ConvertOptions{Controller: StatefulStateController}, 3},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tk := Kubernetes{}\n\t\t// Run Transform\n\t\tobjs, err := k.Transform(test.komposeObject, test.opt)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\t\tif len(objs) != test.expectedNumObjs {\n\t\t\tt.Errorf(\"Expected %d objects returned, got %d\", test.expectedNumObjs, len(objs))\n\t\t}\n\n\t\tvar foundSVC, foundD, foundDS, foundDC, foundSS bool\n\t\tname := \"app\"\n\t\tlabels := transformer.ConfigLabels(name)\n\t\tconfig := test.komposeObject.ServiceConfigs[name]\n\t\tlabelsWithNetwork := transformer.ConfigLabelsWithNetwork(name, config.Network)\n\t\t// Check results\n\t\tfor _, obj := range objs {\n\t\t\tif svc, ok := obj.(*api.Service); ok {\n\t\t\t\tif err := checkService(config, svc, labels); err != nil {\n\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t}\n\t\t\t\tif err := checkMeta(config, svc.ObjectMeta, name, true); err != nil {\n\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t}\n\t\t\t\tfoundSVC = true\n\t\t\t}\n\n\t\t\tif test.opt.CreateD {\n\t\t\t\tif d, ok := obj.(*appsv1.Deployment); ok {\n\t\t\t\t\tif err := checkPodTemplate(config, d.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif err := checkMeta(config, d.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif test.opt.IsReplicaSetFlag {\n\t\t\t\t\t\tif (int)(*d.Spec.Replicas) != replicas {\n\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", replicas, d.Spec.Replicas)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (int)(*d.Spec.Replicas) != newServiceConfig().Replicas {\n\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", newServiceConfig().Replicas, d.Spec.Replicas)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfoundD = true\n\t\t\t\t}\n\n\t\t\t\tif u, ok := obj.(*unstructured.Unstructured); ok {\n\t\t\t\t\tif u.GetKind() == \"Deployment\" {\n\t\t\t\t\t\tu.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\t\t\tGroup:   \"apps\",\n\t\t\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t\t\t\tKind:    \"Deployment\",\n\t\t\t\t\t\t})\n\t\t\t\t\t\tdata, err := json.Marshal(u)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar d appsv1.Deployment\n\t\t\t\t\t\tif err := json.Unmarshal(data, &d); err == nil {\n\t\t\t\t\t\t\tif err := checkPodTemplate(config, d.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif err := checkMeta(config, d.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif test.opt.IsReplicaSetFlag {\n\t\t\t\t\t\t\t\tif (int)(*d.Spec.Replicas) != replicas {\n\t\t\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", replicas, d.Spec.Replicas)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (int)(*d.Spec.Replicas) != newServiceConfig().Replicas {\n\t\t\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", newServiceConfig().Replicas, d.Spec.Replicas)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfoundD = true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif test.opt.CreateDS {\n\t\t\t\tif ds, ok := obj.(*appsv1.DaemonSet); ok {\n\t\t\t\t\tif err := checkPodTemplate(config, ds.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif err := checkMeta(config, ds.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif ds.Spec.Selector == nil || len(ds.Spec.Selector.MatchLabels) == 0 {\n\t\t\t\t\t\tt.Errorf(\"Expect selector be set, got: %#v\", ds.Spec.Selector)\n\t\t\t\t\t}\n\t\t\t\t\tfoundDS = true\n\t\t\t\t}\n\n\t\t\t\tif u, ok := obj.(*unstructured.Unstructured); ok {\n\t\t\t\t\tif u.GetKind() == \"DaemonSet\" {\n\t\t\t\t\t\tu.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\t\t\tGroup:   \"apps\",\n\t\t\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t\t\t\tKind:    \"DaemonSet\",\n\t\t\t\t\t\t})\n\t\t\t\t\t\tdata, err := json.Marshal(u)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar ds appsv1.DaemonSet\n\t\t\t\t\t\tif err := json.Unmarshal(data, &ds); err == nil {\n\t\t\t\t\t\t\tif err := checkPodTemplate(config, ds.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif err := checkMeta(config, ds.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfoundDS = true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif test.opt.Controller == StatefulStateController {\n\t\t\t\tif ss, ok := obj.(*appsv1.StatefulSet); ok {\n\t\t\t\t\tif err := checkPodTemplate(config, ss.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif err := checkMeta(config, ss.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif test.opt.IsReplicaSetFlag {\n\t\t\t\t\t\tif (int)(*ss.Spec.Replicas) != replicas {\n\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", replicas, ss.Spec.Replicas)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (int)(*ss.Spec.Replicas) != newServiceConfig().Replicas {\n\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", newServiceConfig().Replicas, ss.Spec.Replicas)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfoundSS = true\n\t\t\t\t}\n\n\t\t\t\tif u, ok := obj.(*unstructured.Unstructured); ok {\n\t\t\t\t\tif u.GetKind() == \"Statefulset\" {\n\t\t\t\t\t\tu.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\t\t\tGroup:   \"apps\",\n\t\t\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t\t\t\tKind:    \"Statefulset\",\n\t\t\t\t\t\t})\n\t\t\t\t\t\tdata, err := json.Marshal(u)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar d appsv1.Deployment\n\t\t\t\t\t\tif err := json.Unmarshal(data, &d); err == nil {\n\t\t\t\t\t\t\tif err := checkPodTemplate(config, d.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif err := checkMeta(config, d.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif test.opt.IsReplicaSetFlag {\n\t\t\t\t\t\t\t\tif (int)(*d.Spec.Replicas) != replicas {\n\t\t\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", replicas, d.Spec.Replicas)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (int)(*d.Spec.Replicas) != newServiceConfig().Replicas {\n\t\t\t\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", newServiceConfig().Replicas, d.Spec.Replicas)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfoundSS = true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// TODO: k8s & openshift transformer is now separated; either separate the test or combine the transformer\n\t\t\tif test.opt.CreateDeploymentConfig {\n\t\t\t\tif dc, ok := obj.(*deployapi.DeploymentConfig); ok {\n\t\t\t\t\tif err := checkPodTemplate(config, *dc.Spec.Template, labelsWithNetwork); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif err := checkMeta(config, dc.ObjectMeta, name, true); err != nil {\n\t\t\t\t\t\tt.Errorf(\"%v\", err)\n\t\t\t\t\t}\n\t\t\t\t\tif (int)(dc.Spec.Replicas) != replicas {\n\t\t\t\t\t\tt.Errorf(\"Expected %d replicas, got %d\", replicas, dc.Spec.Replicas)\n\t\t\t\t\t}\n\t\t\t\t\tif len(dc.Spec.Selector) == 0 {\n\t\t\t\t\t\tt.Errorf(\"Expect selector be set, got: %#v\", dc.Spec.Selector)\n\t\t\t\t\t}\n\t\t\t\t\tfoundDC = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif !foundSVC {\n\t\t\tt.Errorf(\"Unexpected Service not created\")\n\t\t}\n\t\tif test.opt.CreateD != foundD {\n\t\t\tt.Errorf(\"Expected create Deployment: %v, found Deployment: %v\", test.opt.CreateD, foundD)\n\t\t}\n\t\tif test.opt.CreateDS != foundDS {\n\t\t\tt.Errorf(\"Expected create Daemon Set: %v, found Daemon Set: %v\", test.opt.CreateDS, foundDS)\n\t\t}\n\n\t\tif test.opt.Controller == StatefulStateController && !foundSS {\n\t\t\tt.Errorf(\"Expected create StatefulStateController\")\n\t\t}\n\t\tif test.opt.CreateDeploymentConfig != foundDC {\n\t\t\tt.Errorf(\"Expected create Deployment Config: %v, found Deployment Config: %v\", test.opt.CreateDeploymentConfig, foundDC)\n\t\t}\n\t}\n}\n\nfunc TestConvertRestartOptions(t *testing.T) {\n\tvar opt kobject.ConvertOptions\n\tvar k Kubernetes\n\n\ttestCases := map[string]struct {\n\t\tsvc           kobject.KomposeObject\n\t\trestartPolicy api.RestartPolicy\n\t}{\n\t\t\"'restart' is set to 'no'\":         {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{\"app\": {Image: \"foobar\", Restart: \"no\"}}}, api.RestartPolicyNever},\n\t\t\"'restart' is set to 'on-failure'\": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{\"app\": {Image: \"foobar\", Restart: \"on-failure\"}}}, api.RestartPolicyOnFailure},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test Case:\", name)\n\n\t\tobjs, err := k.Transform(test.svc, opt)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\n\t\tif len(objs) != 1 {\n\t\t\tt.Errorf(\"Expected only one pod, more elements generated.\")\n\t\t}\n\n\t\tfor _, obj := range objs {\n\t\t\tif pod, ok := obj.(*api.Pod); ok {\n\t\t\t\tif pod.Spec.RestartPolicy != test.restartPolicy {\n\t\t\t\t\tt.Errorf(\"Expected restartPolicy as %s, got %#v\", test.restartPolicy, pod.Spec.RestartPolicy)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"Expected 'pod' object not found one\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestRestartOnFailure(t *testing.T) {\n\tkobjectWithRestartOnFailure := newKomposeObject()\n\tserviceConfig := kobjectWithRestartOnFailure.ServiceConfigs[\"app\"]\n\tserviceConfig.Restart = \"on-failure\"\n\tkobjectWithRestartOnFailure.ServiceConfigs = map[string]kobject.ServiceConfig{\"app\": serviceConfig}\n\n\t// define all test cases for RestartOnFailure function\n\treplicas := 2\n\ttestCase := map[string]struct {\n\t\tkomposeObject kobject.KomposeObject\n\t\topt           kobject.ConvertOptions\n\t}{\n\t\t// objects generated are deployment, service and replication controller\n\t\t\"Do not Create Deployment (D) with restart:'on-failure'\":             {kobjectWithRestartOnFailure, kobject.ConvertOptions{IsDeploymentFlag: true, Replicas: replicas}},\n\t\t\"Do not Create DaemonSet (DS) with restart:'on-failure'\":             {kobjectWithRestartOnFailure, kobject.ConvertOptions{IsDaemonSetFlag: true, Replicas: replicas}},\n\t\t\"Do not Create ReplicationController (RC) with restart:'on-failure'\": {kobjectWithRestartOnFailure, kobject.ConvertOptions{IsReplicationControllerFlag: true, Replicas: replicas}},\n\t}\n\n\tfor name, test := range testCase {\n\t\tt.Log(\"Test case:\", name)\n\t\tk := Kubernetes{}\n\t\t_, err := k.Transform(test.komposeObject, test.opt)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Expected nil error, got %v instead\", err)\n\t\t}\n\t}\n}\n\nfunc TestInitPodSpec(t *testing.T) {\n\tname := \"foo\"\n\tk := Kubernetes{}\n\tresult := k.InitPodSpec(name, newServiceConfig().Image, \"\")\n\tif result.Containers[0].Name != \"foo\" && result.Containers[0].Image != \"image\" {\n\t\tt.Fatalf(\"Pod object not found\")\n\t}\n}\n\nfunc TestConfigTmpfs(t *testing.T) {\n\tname := \"foo\"\n\tk := Kubernetes{}\n\tresultVolumeMount, resultVolume := k.ConfigTmpfs(name, newServiceConfig())\n\n\tif resultVolumeMount[0].Name != \"foo-tmpfs0\" || resultVolume[0].EmptyDir.Medium != \"Memory\" {\n\t\tt.Fatalf(\"Tmpfs not found\")\n\t}\n}\n\nfunc TestConfigCapabilities(t *testing.T) {\n\ttestCases := map[string]struct {\n\t\tservice kobject.ServiceConfig\n\t\tresult  api.Capabilities\n\t}{\n\t\t\"ConfigCapsWithAddDrop\": {kobject.ServiceConfig{CapAdd: []string{\"CHOWN\", \"SETUID\"}, CapDrop: []string{\"KILL\"}}, api.Capabilities{Add: []api.Capability{api.Capability(\"CHOWN\"), api.Capability(\"SETUID\")}, Drop: []api.Capability{api.Capability(\"KILL\")}}},\n\t\t\"ConfigCapsNoAddDrop\":   {kobject.ServiceConfig{CapAdd: nil, CapDrop: nil}, api.Capabilities{Add: []api.Capability{}, Drop: []api.Capability{}}},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tresult := ConfigCapabilities(test.service)\n\t\tif !reflect.DeepEqual(result.Add, test.result.Add) || !reflect.DeepEqual(result.Drop, test.result.Drop) {\n\t\t\tt.Errorf(\"Not expected result for ConfigCapabilities\")\n\t\t}\n\t}\n}\n\nfunc TestConfigAffinity(t *testing.T) {\n\ttestCases := map[string]struct {\n\t\tservice kobject.ServiceConfig\n\t\tresult  *api.Affinity\n\t}{\n\t\t\"ConfigAffinity\": {\n\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\tPlacement: kobject.Placement{\n\t\t\t\t\tPositiveConstraints: map[string]string{\n\t\t\t\t\t\t\"foo\": \"bar\",\n\t\t\t\t\t},\n\t\t\t\t\tNegativeConstraints: map[string]string{\n\t\t\t\t\t\t\"baz\": \"qux\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: &api.Affinity{\n\t\t\t\tNodeAffinity: &api.NodeAffinity{\n\t\t\t\t\tRequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{\n\t\t\t\t\t\tNodeSelectorTerms: []api.NodeSelectorTerm{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tMatchExpressions: []api.NodeSelectorRequirement{\n\t\t\t\t\t\t\t\t\t{Key: \"foo\", Operator: api.NodeSelectorOpIn, Values: []string{\"bar\"}},\n\t\t\t\t\t\t\t\t\t{Key: \"baz\", Operator: api.NodeSelectorOpNotIn, Values: []string{\"qux\"}},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"ConfigAffinity (nil)\": {\n\t\t\tkobject.ServiceConfig{},\n\t\t\tnil,\n\t\t},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tresult := ConfigAffinity(test.service)\n\t\tif !reflect.DeepEqual(result, test.result) {\n\t\t\tt.Errorf(\"Not expected result for ConfigAffinity\")\n\t\t}\n\t}\n}\n\nfunc TestConfigTopologySpreadConstraints(t *testing.T) {\n\tserviceName := \"app\"\n\ttestCases := map[string]struct {\n\t\tservice kobject.ServiceConfig\n\t\tresult  []api.TopologySpreadConstraint\n\t}{\n\t\t\"ConfigTopologySpreadConstraint\": {\n\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\tName: serviceName,\n\t\t\t\tPlacement: kobject.Placement{\n\t\t\t\t\tPreferences: []string{\n\t\t\t\t\t\t\"zone\", \"ssd\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: []api.TopologySpreadConstraint{\n\t\t\t\t{\n\t\t\t\t\tMaxSkew:           2,\n\t\t\t\t\tTopologyKey:       \"zone\",\n\t\t\t\t\tWhenUnsatisfiable: api.ScheduleAnyway,\n\t\t\t\t\tLabelSelector: &metav1.LabelSelector{\n\t\t\t\t\t\tMatchLabels: transformer.ConfigLabels(serviceName),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tMaxSkew:           1,\n\t\t\t\t\tTopologyKey:       \"ssd\",\n\t\t\t\t\tWhenUnsatisfiable: api.ScheduleAnyway,\n\t\t\t\t\tLabelSelector: &metav1.LabelSelector{\n\t\t\t\t\t\tMatchLabels: transformer.ConfigLabels(serviceName),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tresult := ConfigTopologySpreadConstraints(test.service)\n\t\tif !reflect.DeepEqual(result, test.result) {\n\t\t\tt.Errorf(\"Not expected result for ConfigTopologySpreadConstraints\")\n\t\t}\n\t}\n}\n\nfunc TestMultipleContainersInPod(t *testing.T) {\n\tgroupName := \"pod_group\"\n\n\tcreateConfig := func(name string, containerName string) kobject.ServiceConfig {\n\t\tconfig := newSimpleServiceConfig()\n\t\tconfig.Labels = map[string]string{compose.LabelServiceGroup: groupName}\n\t\tconfig.Name = name\n\t\tif containerName != \"\" {\n\t\t\tconfig.ContainerName = containerName\n\t\t}\n\t\tconfig.Volumes = []kobject.Volumes{\n\t\t\t{\n\t\t\t\tVolumeName: \"mountVolume\",\n\t\t\t\tMountPath:  \"/data-dir\",\n\t\t\t},\n\t\t}\n\t\treturn config\n\t}\n\n\ttestCases := map[string]struct {\n\t\tkomposeObject   kobject.KomposeObject\n\t\topt             kobject.ConvertOptions\n\t\texpectedNumObjs int\n\t\texpectedNames   []string\n\t}{\n\t\t\"Converted multiple containers to Deployments (D)\": {\n\t\t\tkobject.KomposeObject{\n\t\t\t\tServiceConfigs: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"app1\": createConfig(\"app1\", \"app1\"),\n\t\t\t\t\t\"app2\": createConfig(\"app2\", \"app2\"),\n\t\t\t\t},\n\t\t\t}, kobject.ConvertOptions{ServiceGroupMode: \"label\", CreateD: true}, 2, []string{\"app1\", \"app2\"}},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tk := Kubernetes{}\n\t\t// Run Transform\n\t\tobjs, err := k.Transform(test.komposeObject, test.opt)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\t\tif len(objs) != test.expectedNumObjs {\n\t\t\tt.Errorf(\"Expected %d objects returned, got %d\", test.expectedNumObjs, len(objs))\n\t\t}\n\n\t\t// Check results\n\t\tfor _, obj := range objs {\n\t\t\tif svc, ok := obj.(*api.Service); ok {\n\t\t\t\tif svc.Name != groupName {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", groupName, svc.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\t\tif deployment.Name != groupName {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", groupName, deployment.Name)\n\t\t\t\t}\n\t\t\t\tif len(deployment.Spec.Template.Spec.Containers) != 2 {\n\t\t\t\t\tt.Errorf(\"Expected %d returned, got %d\", 2, len(deployment.Spec.Template.Spec.Containers))\n\t\t\t\t}\n\t\t\t\tnameSet := make(map[string]api.Container)\n\t\t\t\tfor _, container := range deployment.Spec.Template.Spec.Containers {\n\t\t\t\t\tnameSet[container.Name] = container\n\t\t\t\t}\n\t\t\t\tif container, ok := nameSet[test.expectedNames[0]]; !ok {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", test.expectedNames[0], container.Name)\n\t\t\t\t} else if len(container.VolumeMounts) != 1 {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", 1, len(container.VolumeMounts))\n\t\t\t\t}\n\t\t\t\tif container, ok := nameSet[test.expectedNames[1]]; !ok {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", test.expectedNames[1], container.Name)\n\t\t\t\t} else if len(container.VolumeMounts) != 1 {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", 1, len(container.VolumeMounts))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestServiceAccountNameOnMultipleContainers(t *testing.T) {\n\tgroupName := \"pod_group\"\n\tserviceAccountName := \"my-service\"\n\n\tcreateConfigs := func(labels map[string]string) map[string]kobject.ServiceConfig {\n\t\tcreateConfig := func(name string) kobject.ServiceConfig {\n\t\t\tconfig := newSimpleServiceConfig()\n\t\t\tconfig.Labels = map[string]string{compose.LabelServiceGroup: groupName}\n\t\t\tfor k, v := range labels {\n\t\t\t\tconfig.Labels[k] = v\n\t\t\t}\n\t\t\tconfig.Name = name\n\t\t\tconfig.ContainerName = \"\"\n\t\t\tconfig.Volumes = []kobject.Volumes{\n\t\t\t\t{\n\t\t\t\t\tVolumeName: \"mountVolume\",\n\t\t\t\t\tMountPath:  \"/data\",\n\t\t\t\t},\n\t\t\t}\n\t\t\treturn config\n\t\t}\n\t\treturn map[string]kobject.ServiceConfig{\"app1\": createConfig(\"app1\"), \"app2\": createConfig(\"app2\")}\n\t}\n\n\ttestCases := map[string]struct {\n\t\tkomposeObject      kobject.KomposeObject\n\t\texpectedLabelNames []string\n\t}{\n\t\t\"Converted multiple containers with ServiceAccountName\": {\n\t\t\tkobject.KomposeObject{\n\t\t\t\tServiceConfigs: createConfigs(map[string]string{compose.LabelServiceAccountName: serviceAccountName}),\n\t\t\t}, []string{serviceAccountName}},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tk := Kubernetes{}\n\t\t// Run Transform\n\t\tobjs, err := k.Transform(test.komposeObject, kobject.ConvertOptions{ServiceGroupMode: \"label\", CreateD: true})\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\n\t\t// Check results\n\t\tfor _, obj := range objs {\n\t\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\t\tif deployment.Name != groupName {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", groupName, deployment.Name)\n\t\t\t\t}\n\t\t\t\tif deployment.Spec.Template.Spec.ServiceAccountName != serviceAccountName {\n\t\t\t\t\tt.Errorf(\"Expected %v returned, got %v\", serviceAccountName, deployment.Spec.Template.Spec.ServiceAccountName)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestHealthCheckOnMultipleContainers(t *testing.T) {\n\tgroupName := \"pod_group\"\n\n\tcreateHealthCheck := func(TCPPort int32) kobject.HealthCheck {\n\t\treturn kobject.HealthCheck{\n\t\t\tTCPPort: TCPPort,\n\t\t}\n\t}\n\n\tcreateConfig := func(name string, livenessTCPPort, readinessTCPPort int32) kobject.ServiceConfig {\n\t\tconfig := newSimpleServiceConfig()\n\t\tconfig.Labels = map[string]string{compose.LabelServiceGroup: groupName}\n\t\tconfig.Name = name\n\t\tconfig.ContainerName = name\n\t\tconfig.HealthChecks.Liveness = createHealthCheck(livenessTCPPort)\n\t\tconfig.HealthChecks.Readiness = createHealthCheck(readinessTCPPort)\n\t\treturn config\n\t}\n\n\ttestCases := map[string]struct {\n\t\tkomposeObject      kobject.KomposeObject\n\t\topt                kobject.ConvertOptions\n\t\texpectedContainers map[string]api.Container\n\t}{\n\t\t\"Converted multiple containers to Deployments\": {\n\t\t\tkobject.KomposeObject{\n\t\t\t\tServiceConfigs: map[string]kobject.ServiceConfig{\n\t\t\t\t\t\"app1\": createConfig(\"app1\", 8081, 9091),\n\t\t\t\t\t\"app2\": createConfig(\"app2\", 8082, 9092),\n\t\t\t\t},\n\t\t\t},\n\t\t\tkobject.ConvertOptions{ServiceGroupMode: \"label\", CreateD: true},\n\t\t\tmap[string]api.Container{\n\t\t\t\t\"app1\": {\n\t\t\t\t\tLivenessProbe:  configProbe(createHealthCheck(8081)),\n\t\t\t\t\tReadinessProbe: configProbe(createHealthCheck(9091)),\n\t\t\t\t},\n\t\t\t\t\"app2\": {\n\t\t\t\t\tLivenessProbe:  configProbe(createHealthCheck(8082)),\n\t\t\t\t\tReadinessProbe: configProbe(createHealthCheck(9092)),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case:\", name)\n\t\tk := Kubernetes{}\n\t\t// Run Transform\n\t\tobjs, err := k.Transform(test.komposeObject, test.opt)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t\t}\n\n\t\t// Check results\n\t\tfor _, obj := range objs {\n\t\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\t\tif len(deployment.Spec.Template.Spec.Containers) != len(test.expectedContainers) {\n\t\t\t\t\tt.Errorf(\"Containers len is not equal, expected %d, got %d\",\n\t\t\t\t\t\tlen(deployment.Spec.Template.Spec.Containers), len(test.expectedContainers))\n\t\t\t\t}\n\t\t\t\tfor _, result := range deployment.Spec.Template.Spec.Containers {\n\t\t\t\t\texpected, ok := test.expectedContainers[result.Name]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tt.Errorf(\"Container %s doesn't expected\", result.Name)\n\t\t\t\t\t}\n\t\t\t\t\tif !reflect.DeepEqual(result.LivenessProbe, expected.LivenessProbe) {\n\t\t\t\t\t\tt.Errorf(\"Container %s: LivenessProbe expected %v returned, got %v\", result.Name, expected.LivenessProbe, result.LivenessProbe)\n\t\t\t\t\t}\n\t\t\t\t\tif !reflect.DeepEqual(result.ReadinessProbe, expected.ReadinessProbe) {\n\t\t\t\t\t\tt.Errorf(\"Container %s: ReadinessProbe expected %v returned, got %v\", result.Name, expected.ReadinessProbe, result.ReadinessProbe)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCreatePVC(t *testing.T) {\n\tstorageClassName := \"custom-storage-class-name\"\n\tk := Kubernetes{}\n\tresult, err := k.CreatePVC(\"\", \"\", PVCRequestSize, \"\", storageClassName)\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.CreatePVC failed\"))\n\t}\n\tif *result.Spec.StorageClassName != storageClassName {\n\t\tt.Errorf(\"Expected %s returned, got %s\", storageClassName, *result.Spec.StorageClassName)\n\t}\n}\n\nfunc TestCreateHostPortAndProtocol(t *testing.T) {\n\tgroupName := \"pod_group\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newKomposeObjectHostPortProtocolConfig()},\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{ServiceGroupMode: groupName})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tcontainer := deployment.Spec.Template.Spec.Containers[0]\n\t\t\tport := container.Ports[0]\n\t\t\tcontainerPort := port.ContainerPort\n\t\t\thostPort := port.HostPort\n\t\t\tprotocol := port.Protocol\n\n\t\t\texpectedPort := komposeObject.ServiceConfigs[\"app\"].Port[0]\n\t\t\texpectedContainerPort := expectedPort.ContainerPort\n\t\t\texpectedHostPort := expectedPort.HostPort\n\t\t\texpectedProtocol := expectedPort.Protocol\n\n\t\t\tif containerPort != expectedContainerPort {\n\t\t\t\tt.Errorf(\"Expected container port %v, got %v\", expectedContainerPort, containerPort)\n\t\t\t}\n\n\t\t\tif hostPort != expectedHostPort {\n\t\t\t\tt.Errorf(\"Expected host port %v, got %v\", expectedHostPort, hostPort)\n\t\t\t}\n\n\t\t\tif protocol != api.Protocol(expectedProtocol) {\n\t\t\t\tt.Errorf(\"Expected protocol %v, got %v\", expectedProtocol, protocol)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestServiceExternalTrafficPolicy(t *testing.T) {\n\tgroupName := \"pod_group\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfigWithExternalTrafficPolicy()},\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{ServiceGroupMode: groupName})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif service, ok := obj.(*api.Service); ok {\n\t\t\tserviceExternalTrafficPolicy := string(service.Spec.ExternalTrafficPolicy)\n\t\t\tif serviceExternalTrafficPolicy != strings.ToLower(string(api.ServiceExternalTrafficPolicyTypeLocal)) {\n\t\t\t\tt.Errorf(\"Expected Local as external lifecycle policy, got %v\", serviceExternalTrafficPolicy)\n\t\t\t}\n\t\t\tserviceType := service.Spec.Type\n\t\t\tif serviceType != api.ServiceTypeLoadBalancer {\n\t\t\t\tt.Errorf(\"Expected LoadBalancer as service type, got %v\", serviceType)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestVolumeMountSubPath(t *testing.T) {\n\tgroupName := \"pod_group\"\n\texpectedSubPathValue := \"test-subpath\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfigWithServiceVolumeMount(expectedSubPathValue)},\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{ServiceGroupMode: groupName})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tvolMountSubPath := deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].SubPath\n\t\t\tif volMountSubPath != expectedSubPathValue {\n\t\t\t\tt.Errorf(\"Expected VolumeMount Subpath %v, got %v\", expectedSubPathValue, volMountSubPath)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestNetworkPoliciesGeneration(t *testing.T) {\n\tgroupName := \"pod_group\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfig()},\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{ServiceGroupMode: groupName, GenerateNetworkPolicies: true})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif np, ok := obj.(*networkingv1.NetworkPolicy); ok {\n\t\t\tmatchLabelsLength := len(np.Spec.PodSelector.MatchLabels)\n\t\t\tif matchLabelsLength == 0 {\n\t\t\t\tt.Errorf(\"Expected length of Network Policy PodSelector to be greater than 0, got %v\", matchLabelsLength)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestServiceGroupModeImagePullSecrets(t *testing.T) {\n\tgroupName := \"pod_group\"\n\tserviceConfig := newServiceConfig()\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": serviceConfig},\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{ServiceGroupMode: groupName, GenerateNetworkPolicies: true})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\texpectedSecretsLen := len(serviceConfig.ImagePullSecret)\n\tfor _, obj := range objs {\n\t\tif deployment, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tsecretsLen := len(deployment.Spec.Template.Spec.ImagePullSecrets)\n\t\t\tif secretsLen != expectedSecretsLen {\n\t\t\t\tt.Errorf(\"Expected length of Deployment ImagePullSecrets to be equal to %v, got %v\", expectedSecretsLen, secretsLen)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestNamespaceGeneration(t *testing.T) {\n\tns := \"app\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfig()},\n\t\tNamespace:      ns,\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif namespace, ok := obj.(*api.Namespace); ok {\n\t\t\tif strings.ToLower(ns) != strings.ToLower(namespace.ObjectMeta.Name) {\n\t\t\t\tt.Errorf(\"Expected namespace name %v, got %v\", ns, namespace.ObjectMeta.Name)\n\t\t\t}\n\t\t}\n\t\tif dep, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tif dep.ObjectMeta.Namespace != ns {\n\t\t\t\tt.Errorf(\"Expected deployment namespace %v, got %v\", ns, dep.ObjectMeta.Namespace)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Test namespace generation with namespace being blank / \"\"\nfunc TestNamespaceGenerationBlank(t *testing.T) {\n\tns := \"\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfig()},\n\t\tNamespace:      ns,\n\t}\n\tk := Kubernetes{}\n\tobjs, err := k.Transform(komposeObject, kobject.ConvertOptions{})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif namespace, ok := obj.(*api.Namespace); ok {\n\t\t\tif strings.ToLower(ns) != strings.ToLower(namespace.ObjectMeta.Name) {\n\t\t\t\tt.Errorf(\"Expected namespace name %v, got %v\", ns, namespace.ObjectMeta.Name)\n\t\t\t}\n\t\t}\n\t\tif dep, ok := obj.(*appsv1.Deployment); ok {\n\t\t\tif dep.ObjectMeta.Namespace != ns {\n\t\t\t\tt.Errorf(\"Expected deployment namespace %v, got %v\", ns, dep.ObjectMeta.Namespace)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestKubernetes_CreateSecrets(t *testing.T) {\n\tvar komposeDefaultObject []kobject.KomposeObject\n\tdataSecrets := []SecretsConfig{\n\t\t{\n\t\t\tnameSecretConfig: \"config-ini\",\n\t\t\tnameSecret:       \"debug-config-ini\",\n\t\t\tpathFile:         \"../../../docs/CNAME\",\n\t\t},\n\t\t{\n\t\t\tnameSecretConfig: \"new-config-init\",\n\t\t\tnameSecret:       \"new-debug-config-ini\",\n\t\t\tpathFile:         \"../../../docs/CNAME\",\n\t\t},\n\t}\n\n\tfor i := 0; i < len(dataSecrets); i++ {\n\t\tkomposeDefaultObject = append(komposeDefaultObject, newKomposeObject())\n\t\tkomposeDefaultObject[i].Secrets = newSecrets(dataSecrets[i])\n\t}\n\n\ttype fields struct {\n\t\tOpt kobject.ConvertOptions\n\t}\n\ttype args struct {\n\t\tkomposeObject kobject.KomposeObject\n\t}\n\n\ttests := []struct {\n\t\tname    string\n\t\tfields  fields\n\t\targs    args\n\t\twant    []*api.Secret\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"CreateSecrets from default KomposeObject and secrets taken from CNAME file\",\n\t\t\targs: args{\n\t\t\t\tkomposeObject: komposeDefaultObject[0],\n\t\t\t},\n\t\t\twant: []*api.Secret{\n\t\t\t\t{\n\t\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\t\tKind:       \"Secret\",\n\t\t\t\t\t\tAPIVersion: \"v1\",\n\t\t\t\t\t},\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:   FormatResourceName(dataSecrets[0].nameSecretConfig),\n\t\t\t\t\t\tLabels: transformer.ConfigLabels(dataSecrets[0].nameSecretConfig),\n\t\t\t\t\t},\n\t\t\t\t\tType: api.SecretTypeOpaque,\n\t\t\t\t\tData: map[string][]byte{dataSecrets[0].nameSecretConfig: []byte(\"kompose.io\")},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"CreateSecrets from default KomposeObject and secrets taken from CNAME file\",\n\t\t\targs: args{\n\t\t\t\tkomposeObject: komposeDefaultObject[1],\n\t\t\t},\n\t\t\twant: []*api.Secret{\n\t\t\t\t{\n\t\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\t\tKind:       \"Secret\",\n\t\t\t\t\t\tAPIVersion: \"v1\",\n\t\t\t\t\t},\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:   FormatResourceName(dataSecrets[1].nameSecretConfig),\n\t\t\t\t\t\tLabels: transformer.ConfigLabels(dataSecrets[1].nameSecretConfig),\n\t\t\t\t\t},\n\t\t\t\t\tType: api.SecretTypeOpaque,\n\t\t\t\t\tData: map[string][]byte{dataSecrets[1].nameSecretConfig: []byte(\"kompose.io\")},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tk := &Kubernetes{\n\t\t\t\tOpt: tt.fields.Opt,\n\t\t\t}\n\t\t\tgot, err := k.CreateSecrets(tt.args.komposeObject)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"Kubernetes.CreateSecrets() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"Kubernetes.CreateSecrets() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// struct defines the configuration parameters required for creating a secret\ntype SecretsConfig struct {\n\tnameSecretConfig string\n\tnameSecret       string\n\tpathFile         string\n}\n\n// creates a new instance of types.Secrets based on the provided SecretsConfig parameter\nfunc newSecrets(stringsSecretConfig SecretsConfig) types.Secrets {\n\treturn types.Secrets{\n\t\tstringsSecretConfig.nameSecretConfig: types.SecretConfig{\n\t\t\tName: stringsSecretConfig.nameSecret,\n\t\t\tFile: stringsSecretConfig.pathFile,\n\t\t},\n\t}\n}\n\n// TestPargeEnvFiletoConfigMaps tests the conversion of environment variable files to ConfigMap objects\nfunc TestPargeEnvFiletoConfigMaps(t *testing.T) {\n\t// Prepare a temp .env file for the expression test\n\ttempFile, err := os.CreateTemp(\"\", \".env\")\n\tif err != nil {\n\t\tt.Fatalf(\"Failed to create temp env file: %v\", err)\n\t}\n\tdefer os.Remove(tempFile.Name())\n\tcontent := []byte(`FOO=bar\nBAR=${FOO}_baz\nDOC_ENGINE=${DOC_ENGINE:-elasticsearch}\nCOMPOSE_PROFILES=${DOC_ENGINE}\nUNDEFINED_VAR=${MISSING_VAR:-default_value}\n`)\n\tif _, err := tempFile.Write(content); err != nil {\n\t\tt.Fatalf(\"Failed to write to temp env file: %v\", err)\n\t}\n\ttempFile.Close()\n\n\ttempFileName := filepath.Base(tempFile.Name())\n\ttestCases := map[string]struct {\n\t\tservice kobject.ServiceConfig\n\t\topt     kobject.ConvertOptions\n\t\twant    int\n\t\tcheck   func(t *testing.T, cms []runtime.Object)\n\t}{\n\t\t\"Env file with variable expressions\": {\n\t\t\tservice: kobject.ServiceConfig{\n\t\t\t\tName: \"test-app\",\n\t\t\t\tEnvironment: []kobject.EnvVar{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:  \"DOC_ENGINE\",\n\t\t\t\t\t\tValue: \"test-env\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tEnvFile: []string{tempFileName},\n\t\t\t},\n\t\t\topt:  kobject.ConvertOptions{InputFiles: []string{tempFile.Name()}},\n\t\t\twant: 1,\n\t\t\tcheck: func(t *testing.T, cms []runtime.Object) {\n\t\t\t\tcm, ok := cms[0].(*api.ConfigMap)\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Errorf(\"Returned object is not a ConfigMap\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif cm.Data[\"FOO\"] != \"bar\" {\n\t\t\t\t\tt.Errorf(\"Expected FOO=bar, got %s\", cm.Data[\"FOO\"])\n\t\t\t\t}\n\t\t\t\tif cm.Data[\"BAR\"] != \"bar_baz\" {\n\t\t\t\t\tt.Errorf(\"Expected BAR=bar_baz, got %s\", cm.Data[\"BAR\"])\n\t\t\t\t}\n\t\t\t\tif cm.Data[\"DOC_ENGINE\"] != \"test-env\" {\n\t\t\t\t\tt.Errorf(\"Expected DOC_ENGINE=test-env, got %s\", cm.Data[\"DOC_ENGINE\"])\n\t\t\t\t}\n\t\t\t\tif cm.Data[\"COMPOSE_PROFILES\"] != \"test-env\" {\n\t\t\t\t\tt.Errorf(\"Expected COMPOSE_PROFILES=test-env, got %s\", cm.Data[\"COMPOSE_PROFILES\"])\n\t\t\t\t}\n\t\t\t\tif cm.Data[\"UNDEFINED_VAR\"] != \"default_value\" {\n\t\t\t\t\tt.Errorf(\"Expected UNDEFINED_VAR=default_value, got %s\", cm.Data[\"UNDEFINED_VAR\"])\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t}\n\n\tfor name, tc := range testCases {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tk := Kubernetes{}\n\t\t\tcms := k.PargeEnvFiletoConfigMaps(tc.service.Name, tc.service, tc.opt)\n\t\t\tif len(cms) != tc.want {\n\t\t\t\tt.Errorf(\"Expected %d ConfigMaps, got %d\", tc.want, len(cms))\n\t\t\t}\n\t\t\ttc.check(t, cms)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/transformer/kubernetes/podspec.go",
    "content": "package kubernetes\n\nimport (\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\n\tmapset \"github.com/deckarep/golang-set\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n\tapi \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/resource\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\n// PodSpec holds the spec of k8s pod.\ntype PodSpec struct {\n\tapi.PodSpec\n}\n\n// PodSpecOption holds the function to apply on a PodSpec\ntype PodSpecOption func(*PodSpec)\n\n// AddContainer method is responsible for adding a new container to a k8s Pod.\nfunc AddContainer(service kobject.ServiceConfig, opt kobject.ConvertOptions) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tname := GetContainerName(service)\n\t\timage := service.Image\n\n\t\tif image == \"\" {\n\t\t\timage = name\n\t\t}\n\n\t\tenvs, envsFrom, err := ConfigEnvs(service, opt)\n\t\tif err != nil {\n\t\t\tpanic(\"Unable to load env variables\")\n\t\t}\n\n\t\tpodSpec.Containers = append(podSpec.Containers, api.Container{\n\t\t\tName:           name,\n\t\t\tImage:          image,\n\t\t\tEnv:            envs,\n\t\t\tEnvFrom:        envsFrom,\n\t\t\tCommand:        service.Command,\n\t\t\tArgs:           service.Args,\n\t\t\tWorkingDir:     service.WorkingDir,\n\t\t\tStdin:          service.Stdin,\n\t\t\tTTY:            service.Tty,\n\t\t\tLivenessProbe:  configProbe(service.HealthChecks.Liveness),\n\t\t\tReadinessProbe: configProbe(service.HealthChecks.Readiness),\n\t\t})\n\t\tif service.ImagePullSecret != \"\" {\n\t\t\tpodSpec.ImagePullSecrets = append(podSpec.ImagePullSecrets, api.LocalObjectReference{\n\t\t\t\tName: service.ImagePullSecret,\n\t\t\t})\n\t\t}\n\t\tpodSpec.Affinity = ConfigAffinity(service)\n\t}\n}\n\n// TerminationGracePeriodSeconds method is responsible for attributing the grace period seconds option to a pod\nfunc TerminationGracePeriodSeconds(name string, service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tvar err error\n\t\tif service.StopGracePeriod != \"\" {\n\t\t\tpodSpec.TerminationGracePeriodSeconds, err = DurationStrToSecondsInt(service.StopGracePeriod)\n\t\t\tif err != nil {\n\t\t\t\tlog.Warningf(\"Failed to parse duration \\\"%v\\\" for service \\\"%v\\\"\", service.StopGracePeriod, name)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ResourcesLimits Configure the resource limits\nfunc ResourcesLimits(service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tif service.MemLimit != 0 || service.CPULimit != 0 {\n\t\t\tresourceLimit := api.ResourceList{}\n\n\t\t\tif service.MemLimit != 0 {\n\t\t\t\tresourceLimit[api.ResourceMemory] = *resource.NewQuantity(int64(service.MemLimit), \"RandomStringForFormat\")\n\t\t\t}\n\n\t\t\tif service.CPULimit != 0 {\n\t\t\t\tresourceLimit[api.ResourceCPU] = *resource.NewMilliQuantity(service.CPULimit, resource.DecimalSI)\n\t\t\t}\n\n\t\t\tfor i := range podSpec.Containers {\n\t\t\t\tpodSpec.Containers[i].Resources.Limits = resourceLimit\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ResourcesRequests Configure the resource requests\nfunc ResourcesRequests(service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tif service.MemReservation != 0 || service.CPUReservation != 0 {\n\t\t\tresourceRequests := api.ResourceList{}\n\n\t\t\tif service.MemReservation != 0 {\n\t\t\t\tresourceRequests[api.ResourceMemory] = *resource.NewQuantity(int64(service.MemReservation), \"RandomStringForFormat\")\n\t\t\t}\n\n\t\t\tif service.CPUReservation != 0 {\n\t\t\t\tresourceRequests[api.ResourceCPU] = *resource.NewMilliQuantity(service.CPUReservation, resource.DecimalSI)\n\t\t\t}\n\n\t\t\tfor i := range podSpec.Containers {\n\t\t\t\tpodSpec.Containers[i].Resources.Requests = resourceRequests\n\t\t\t}\n\t\t}\n\t}\n}\n\n// SecurityContext Configure SecurityContext\nfunc SecurityContext(name string, service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\t// Configure resource reservations\n\t\tpodSecurityContext := &api.PodSecurityContext{}\n\n\t\t//set pid namespace mode\n\t\tif service.Pid != \"\" {\n\t\t\tif service.Pid == \"host\" {\n\t\t\t\t// podSecurityContext.HostPID = true\n\t\t\t} else {\n\t\t\t\tlog.Warningf(\"Ignoring PID key for service \\\"%v\\\". Invalid value \\\"%v\\\".\", name, service.Pid)\n\t\t\t}\n\t\t}\n\n\t\t//set supplementalGroups\n\t\tif service.GroupAdd != nil {\n\t\t\tpodSecurityContext.SupplementalGroups = service.GroupAdd\n\t\t}\n\n\t\t//set Pod FsGroup\n\t\tif service.FsGroup != 0 {\n\t\t\tpodSecurityContext.FSGroup = &service.FsGroup\n\t\t}\n\n\t\t// Setup security context\n\t\tsecurityContext := &api.SecurityContext{}\n\t\tif service.Privileged {\n\t\t\tsecurityContext.Privileged = &service.Privileged\n\t\t}\n\t\tif service.User != \"\" {\n\t\t\tswitch userparts := strings.Split(service.User, \":\"); len(userparts) {\n\t\t\tdefault:\n\t\t\t\tlog.Warn(\"Ignoring ill-formed user directive. Must be in format UID or UID:GID.\")\n\t\t\tcase 1:\n\t\t\t\tuid, err := strconv.ParseInt(userparts[0], 10, 64)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warn(\"Ignoring user directive. User to be specified as a UID (numeric).\")\n\t\t\t\t} else {\n\t\t\t\t\tsecurityContext.RunAsUser = &uid\n\t\t\t\t}\n\t\t\tcase 2:\n\t\t\t\tuid, err := strconv.ParseInt(userparts[0], 10, 64)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warn(\"Ignoring user name in user directive. User to be specified as a UID (numeric).\")\n\t\t\t\t} else {\n\t\t\t\t\tsecurityContext.RunAsUser = &uid\n\t\t\t\t}\n\n\t\t\t\tgid, err := strconv.ParseInt(userparts[1], 10, 64)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warn(\"Ignoring group name in user directive. Group to be specified as a GID (numeric).\")\n\t\t\t\t} else {\n\t\t\t\t\tsecurityContext.RunAsGroup = &gid\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Configure capabilities\n\t\tcapabilities := ConfigCapabilities(service)\n\n\t\t//set capabilities if it is not empty\n\t\tif len(capabilities.Add) > 0 || len(capabilities.Drop) > 0 {\n\t\t\tsecurityContext.Capabilities = capabilities\n\t\t}\n\n\t\t// update template only if securityContext is not empty\n\t\tif *securityContext != (api.SecurityContext{}) {\n\t\t\t// select the correct container to update by name\n\t\t\tfor i := range podSpec.Containers {\n\t\t\t\tif podSpec.Containers[i].Name == GetContainerName(service) {\n\t\t\t\t\tpodSpec.Containers[i].SecurityContext = securityContext\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\tif !reflect.DeepEqual(*podSecurityContext, api.PodSecurityContext{}) {\n\t\t\tpodSpec.SecurityContext = podSecurityContext\n\t\t}\n\t}\n}\n\n// SetVolumeNames method return a set of volume names\nfunc SetVolumeNames(volumes []api.Volume) mapset.Set {\n\tset := mapset.NewSet()\n\tfor _, volume := range volumes {\n\t\tset.Add(volume.Name)\n\t}\n\treturn set\n}\n\n// SetVolumes method returns a method that adds the volumes to the pod spec\nfunc SetVolumes(volumes []api.Volume) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tvolumesSet := SetVolumeNames(volumes)\n\t\tcontainerVolumesSet := SetVolumeNames(podSpec.Volumes)\n\t\tfor diffVolumeName := range volumesSet.Difference(containerVolumesSet).Iter() {\n\t\t\tfor _, volume := range volumes {\n\t\t\t\tif volume.Name == diffVolumeName {\n\t\t\t\t\tpodSpec.Volumes = append(podSpec.Volumes, volume)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// SetVolumeMountPaths method returns a set of volumes mount path\nfunc SetVolumeMountPaths(volumesMount []api.VolumeMount) mapset.Set {\n\tset := mapset.NewSet()\n\tfor _, volumeMount := range volumesMount {\n\t\tset.Add(volumeMount.MountPath)\n\t}\n\n\treturn set\n}\n\n// SetVolumeMounts returns a function which adds the volume mounts option to the pod spec\nfunc SetVolumeMounts(volumesMount []api.VolumeMount) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tvolumesMountSet := SetVolumeMountPaths(volumesMount)\n\t\tfor i := range podSpec.Containers {\n\t\t\tcontainerVolumeMountsSet := SetVolumeMountPaths(podSpec.Containers[i].VolumeMounts)\n\t\t\tfor diffVolumeMountPath := range volumesMountSet.Difference(containerVolumeMountsSet).Iter() {\n\t\t\t\tfor _, volumeMount := range volumesMount {\n\t\t\t\t\tif volumeMount.MountPath == diffVolumeMountPath {\n\t\t\t\t\t\tpodSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, volumeMount)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// SetPorts Configure ports\nfunc SetPorts(service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\t// Configure the container ports.\n\t\tports := ConfigPorts(service)\n\t\tfor i := range podSpec.Containers {\n\t\t\tif GetContainerName(service) == podSpec.Containers[i].Name {\n\t\t\t\tpodSpec.Containers[i].Ports = ports\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ImagePullPolicy Configure the image pull policy\nfunc ImagePullPolicy(name string, service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tif policy, err := GetImagePullPolicy(name, service.ImagePullPolicy); err != nil {\n\t\t\tpanic(err)\n\t\t} else {\n\t\t\tfor i := range podSpec.Containers {\n\t\t\t\tpodSpec.Containers[i].ImagePullPolicy = policy\n\t\t\t}\n\t\t}\n\t}\n}\n\n// RestartPolicy Configure the container restart policy.\nfunc RestartPolicy(name string, service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tif restart, err := GetRestartPolicy(name, service.Restart); err != nil {\n\t\t\tpanic(err)\n\t\t} else {\n\t\t\tpodSpec.RestartPolicy = restart\n\t\t}\n\t}\n}\n\n// HostName configure the host name of a pod\nfunc HostName(service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\t// Configure hostname/domain_name settings\n\t\tif service.HostName != \"\" {\n\t\t\tpodSpec.Hostname = service.HostName\n\t\t}\n\t}\n}\n\n// DomainName configure the domain name of a pod\nfunc DomainName(service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tif service.DomainName != \"\" {\n\t\t\tpodSpec.Subdomain = service.DomainName\n\t\t}\n\t}\n}\n\nfunc configProbe(healthCheck kobject.HealthCheck) *api.Probe {\n\tprobe := api.Probe{}\n\t// We check to see if it's blank or disable\n\tif reflect.DeepEqual(healthCheck, kobject.HealthCheck{}) || healthCheck.Disable {\n\t\treturn nil\n\t}\n\n\tif len(healthCheck.Test) > 0 {\n\t\tprobe.ProbeHandler = api.ProbeHandler{\n\t\t\tExec: &api.ExecAction{\n\t\t\t\tCommand: healthCheck.Test,\n\t\t\t},\n\t\t}\n\t} else if !reflect.ValueOf(healthCheck.HTTPPath).IsZero() && !reflect.ValueOf(healthCheck.HTTPPort).IsZero() {\n\t\tprobe.ProbeHandler = api.ProbeHandler{\n\t\t\tHTTPGet: &api.HTTPGetAction{\n\t\t\t\tPath: healthCheck.HTTPPath,\n\t\t\t\tPort: intstr.FromInt(int(healthCheck.HTTPPort)),\n\t\t\t},\n\t\t}\n\t} else if !reflect.ValueOf(healthCheck.TCPPort).IsZero() {\n\t\tprobe.ProbeHandler = api.ProbeHandler{\n\t\t\tTCPSocket: &api.TCPSocketAction{\n\t\t\t\tPort: intstr.FromInt(int(healthCheck.TCPPort)),\n\t\t\t},\n\t\t}\n\t} else {\n\t\tpanic(errors.New(\"Health check must contain a command\"))\n\t}\n\n\tprobe.TimeoutSeconds = healthCheck.Timeout\n\tprobe.PeriodSeconds = healthCheck.Interval\n\tprobe.FailureThreshold = healthCheck.Retries\n\n\t// See issue: https://github.com/docker/cli/issues/116\n\t// StartPeriod has been added to v3.4 of the compose\n\tprobe.InitialDelaySeconds = healthCheck.StartPeriod\n\treturn &probe\n}\n\n// ServiceAccountName is responsible for setting the service account name to the pod spec\nfunc ServiceAccountName(serviceAccountName string) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tpodSpec.ServiceAccountName = serviceAccountName\n\t}\n}\n\n// TopologySpreadConstraints is responsible for setting the topology spread constraints to the pod spec\nfunc TopologySpreadConstraints(service kobject.ServiceConfig) PodSpecOption {\n\treturn func(podSpec *PodSpec) {\n\t\tpodSpec.TopologySpreadConstraints = ConfigTopologySpreadConstraints(service)\n\t}\n}\n\n// Append is responsible for adding the pod spec options to the particular pod\nfunc (podSpec *PodSpec) Append(ops ...PodSpecOption) *PodSpec {\n\tfor _, option := range ops {\n\t\toption(podSpec)\n\t}\n\treturn podSpec\n}\n\n// Get is responsible for returning the pod spec of a particular pod\nfunc (podSpec *PodSpec) Get() api.PodSpec {\n\treturn podSpec.PodSpec\n}\n"
  },
  {
    "path": "pkg/transformer/openshift/openshift.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage openshift\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\t\"github.com/kubernetes/kompose/pkg/transformer/kubernetes\"\n\tdeployapi \"github.com/openshift/api/apps/v1\"\n\tbuildapi \"github.com/openshift/api/build/v1\"\n\timageapi \"github.com/openshift/api/image/v1\"\n\trouteapi \"github.com/openshift/api/route/v1\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tkapi \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\n// OpenShift implements Transformer interface and represents OpenShift transformer\ntype OpenShift struct {\n\t// Anonymous field allows for inheritance. We are basically inheriting\n\t// all of kubernetes.Kubernetes Methods and variables here. We'll overwrite\n\t// some of those methods with our own for openshift.\n\tkubernetes.Kubernetes\n}\n\n// list of all unsupported keys for this transformer\n// Keys are names of variables in kobject struct.\n// this is map to make searching for keys easier\n// to make sure that unsupported key is not going to be reported twice\n// by keeping record if already saw this key in another service\nvar unsupportedKey = map[string]bool{}\n\n// initImageStream initializes ImageStream object\nfunc (o *OpenShift) initImageStream(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions) *imageapi.ImageStream {\n\tif service.Image == \"\" {\n\t\tservice.Image = name\n\t}\n\t// Retrieve tags and image name for mapping\n\tvar importPolicy imageapi.TagImportPolicy\n\tif opt.InsecureRepository {\n\t\timportPolicy = imageapi.TagImportPolicy{Insecure: true}\n\t}\n\n\tvar tags []imageapi.TagReference\n\n\tif service.Build != \"\" || opt.Build != \"build-config\" {\n\t\ttags = append(tags,\n\t\t\timageapi.TagReference{\n\t\t\t\tFrom: &corev1.ObjectReference{\n\t\t\t\t\tKind: \"DockerImage\",\n\t\t\t\t\tName: service.Image,\n\t\t\t\t},\n\t\t\t\tImportPolicy: importPolicy,\n\t\t\t\tName:         GetImageTag(service.Image),\n\t\t\t})\n\t}\n\n\tis := &imageapi.ImageStream{\n\t\tTypeMeta: kapi.TypeMeta{\n\t\t\tKind:       \"ImageStream\",\n\t\t\tAPIVersion: \"image.openshift.io/v1\",\n\t\t},\n\t\tObjectMeta: kapi.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t\tSpec: imageapi.ImageStreamSpec{\n\t\t\tTags: tags,\n\t\t},\n\t}\n\treturn is\n}\n\nfunc initBuildConfig(name string, service kobject.ServiceConfig, repo string, branch string) (*buildapi.BuildConfig, error) {\n\tcontextDir, err := GetAbsBuildContext(service.Build)\n\tenvList := transformer.EnvSort{}\n\tfor envName, envValue := range service.BuildArgs {\n\t\tif *envValue == \"\\x00\" {\n\t\t\t*envValue = os.Getenv(envName)\n\t\t}\n\t\tenvList = append(envList, corev1.EnvVar{Name: envName, Value: *envValue})\n\t}\n\t// Stable sorts data while keeping the original order of equal elements\n\t// we need this because envs are not populated in any random order\n\t// this sorting ensures they are populated in a particular order\n\tsort.Stable(envList)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, name+\"buildconfig cannot be created due to error in creating build context, getAbsBuildContext failed\")\n\t}\n\n\tbc := &buildapi.BuildConfig{\n\t\tTypeMeta: kapi.TypeMeta{\n\t\t\tKind:       \"BuildConfig\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\n\t\tObjectMeta: kapi.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t\tSpec: buildapi.BuildConfigSpec{\n\t\t\tTriggers: []buildapi.BuildTriggerPolicy{\n\t\t\t\t{Type: \"ConfigChange\"},\n\t\t\t},\n\t\t\tRunPolicy: \"Serial\",\n\t\t\tCommonSpec: buildapi.CommonSpec{\n\t\t\t\tSource: buildapi.BuildSource{\n\t\t\t\t\tGit: &buildapi.GitBuildSource{\n\t\t\t\t\t\tRef: branch,\n\t\t\t\t\t\tURI: repo,\n\t\t\t\t\t},\n\t\t\t\t\tContextDir: contextDir,\n\t\t\t\t},\n\t\t\t\tStrategy: buildapi.BuildStrategy{\n\t\t\t\t\tDockerStrategy: &buildapi.DockerBuildStrategy{\n\t\t\t\t\t\tDockerfilePath: service.Dockerfile,\n\t\t\t\t\t\tEnv:            envList,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tOutput: buildapi.BuildOutput{\n\t\t\t\t\tTo: &corev1.ObjectReference{\n\t\t\t\t\t\tKind: \"ImageStreamTag\",\n\t\t\t\t\t\tName: name + \":\" + GetImageTag(service.Image),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\treturn bc, nil\n}\n\n// initDeploymentConfig initializes OpenShifts DeploymentConfig object\nfunc (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceConfig, replicas int) *deployapi.DeploymentConfig {\n\tcontainerName := []string{name}\n\n\t// Properly add tags to the image name\n\ttag := GetImageTag(service.Image)\n\n\t// Use ContainerName if it was set\n\tif service.ContainerName != \"\" {\n\t\tcontainerName = []string{service.ContainerName}\n\t}\n\n\tvar podSpec corev1.PodSpec\n\tif len(service.Configs) > 0 {\n\t\tpodSpec = o.InitPodSpecWithConfigMap(name, \" \", service)\n\t} else {\n\t\tpodSpec = o.InitPodSpec(name, \" \", \"\")\n\t}\n\n\tdc := &deployapi.DeploymentConfig{\n\t\tTypeMeta: kapi.TypeMeta{\n\t\t\tKind:       \"DeploymentConfig\",\n\t\t\tAPIVersion: \"apps.openshift.io/v1\",\n\t\t},\n\t\tObjectMeta: kapi.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t\tSpec: deployapi.DeploymentConfigSpec{\n\t\t\tReplicas: int32(replicas),\n\t\t\tSelector: transformer.ConfigLabels(name),\n\t\t\t//UniqueLabelKey: p.Name,\n\t\t\tTemplate: &corev1.PodTemplateSpec{\n\t\t\t\tObjectMeta: kapi.ObjectMeta{\n\t\t\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t\t\t},\n\t\t\t\tSpec: podSpec,\n\t\t\t},\n\t\t\tTriggers: []deployapi.DeploymentTriggerPolicy{\n\t\t\t\t// Trigger new deploy when DeploymentConfig is created (config change)\n\t\t\t\t{\n\t\t\t\t\tType: deployapi.DeploymentTriggerOnConfigChange,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType: deployapi.DeploymentTriggerOnImageChange,\n\t\t\t\t\tImageChangeParams: &deployapi.DeploymentTriggerImageChangeParams{\n\t\t\t\t\t\t//Automatic - if new tag is detected - update image update inside the pod template\n\t\t\t\t\t\tAutomatic:      true,\n\t\t\t\t\t\tContainerNames: containerName,\n\t\t\t\t\t\tFrom: corev1.ObjectReference{\n\t\t\t\t\t\t\tName: name + \":\" + tag,\n\t\t\t\t\t\t\tKind: \"ImageStreamTag\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tupdate := service.GetOSUpdateStrategy()\n\tif update != nil {\n\t\tdc.Spec.Strategy = deployapi.DeploymentStrategy{\n\t\t\tType:          deployapi.DeploymentStrategyTypeRolling,\n\t\t\tRollingParams: update,\n\t\t}\n\t\tlog.Debugf(\"Set deployment '%s' rolling update: MaxSurge: %s, MaxUnavailable: %s\", name, update.MaxSurge.String(), update.MaxUnavailable.String())\n\t}\n\n\treturn dc\n}\n\nfunc (o *OpenShift) initRoute(name string, service kobject.ServiceConfig, port int32) *routeapi.Route {\n\troute := &routeapi.Route{\n\t\tTypeMeta: kapi.TypeMeta{\n\t\t\tKind:       \"Route\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: kapi.ObjectMeta{\n\t\t\tName:   name,\n\t\t\tLabels: transformer.ConfigLabels(name),\n\t\t},\n\t\tSpec: routeapi.RouteSpec{\n\t\t\tPort: &routeapi.RoutePort{\n\t\t\t\tTargetPort: intstr.IntOrString{\n\t\t\t\t\tIntVal: port,\n\t\t\t\t},\n\t\t\t},\n\t\t\tTo: routeapi.RouteTargetReference{\n\t\t\t\tKind: \"Service\",\n\t\t\t\tName: name,\n\t\t\t},\n\t\t},\n\t}\n\n\tif service.ExposeService != \"true\" {\n\t\troute.Spec.Host = service.ExposeService\n\t}\n\treturn route\n}\n\n// Transform maps komposeObject to openshift objects\n// returns objects that are already sorted in the way that Services are first\nfunc (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) ([]runtime.Object, error) {\n\tnoSupKeys := o.Kubernetes.CheckUnsupportedKey(&komposeObject, unsupportedKey)\n\tfor _, keyName := range noSupKeys {\n\t\tlog.Warningf(\"OpenShift provider doesn't support %s key - ignoring\", keyName)\n\t}\n\t// this will hold all the converted data\n\tvar allobjects []runtime.Object\n\n\tif komposeObject.Namespace != \"\" {\n\t\tns := transformer.CreateNamespace(komposeObject.Namespace)\n\t\tallobjects = append(allobjects, ns)\n\t}\n\n\tvar err error\n\tvar composeFileDir string\n\tbuildRepo := opt.BuildRepo\n\tbuildBranch := opt.BuildBranch\n\n\tif komposeObject.Secrets != nil {\n\t\tsecrets, err := o.CreateSecrets(komposeObject)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"create secrets error\")\n\t\t}\n\t\tfor _, item := range secrets {\n\t\t\tallobjects = append(allobjects, item)\n\t\t}\n\t}\n\n\tsortedKeys := kubernetes.SortedKeys(komposeObject.ServiceConfigs)\n\tfor _, name := range sortedKeys {\n\t\tservice := komposeObject.ServiceConfigs[name]\n\t\tvar objects []runtime.Object\n\n\t\t//replicas\n\t\tvar replica int\n\t\tif opt.IsReplicaSetFlag || service.Replicas == 0 {\n\t\t\treplica = opt.Replicas\n\t\t} else {\n\t\t\treplica = service.Replicas\n\t\t}\n\n\t\t// If Deploy.Mode = Global has been set, make replica = 1 when generating DeploymentConfig\n\t\tif service.DeployMode == \"global\" {\n\t\t\treplica = 1\n\t\t}\n\n\t\t// Must build the images before conversion (got to add service.Image in case 'image' key isn't provided\n\t\t// Check to see if there is an InputFile (required!) before we build the container\n\t\t// Check that there's actually a Build key\n\t\t// Lastly, we must have an Image name to continue\n\t\tif opt.Build == \"local\" && opt.InputFiles != nil && service.Build != \"\" {\n\t\t\t// If there's no \"image\" key, use the name of the container that's built\n\t\t\tif service.Image == \"\" {\n\t\t\t\tservice.Image = name\n\t\t\t}\n\n\t\t\tif service.Image == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"image key required within build parameters in order to build and push service '%s'\", name)\n\t\t\t}\n\n\t\t\t// Build the container!\n\t\t\terr := transformer.BuildDockerImage(service, name)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"Unable to build Docker container for service %v: %v\", name, err)\n\t\t\t}\n\n\t\t\t// Push the built container to the repo!\n\t\t\terr = transformer.PushDockerImageWithOpt(service, name, opt)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"Unable to push Docker image for service %v: %v\", name, err)\n\t\t\t}\n\t\t}\n\n\t\t// Generate pod or cronjob and configmap objects\n\t\tif service.Restart == \"no\" || service.Restart == \"on-failure\" {\n\t\t\t// Error out if Controller Object is specified with restart: 'on-failure'\n\t\t\tif opt.IsDeploymentConfigFlag {\n\t\t\t\treturn nil, errors.New(\"Controller object cannot be specified with restart: 'on-failure'\")\n\t\t\t}\n\n\t\t\tif service.CronJobSchedule != \"\" {\n\t\t\t\tcronJob := o.InitCJ(name, service, service.CronJobSchedule, service.CronJobConcurrencyPolicy, service.CronJobBackoffLimit)\n\t\t\t\tobjects = append(objects, cronJob)\n\t\t\t} else {\n\t\t\t\tpod := o.InitPod(name, service)\n\t\t\t\tobjects = append(objects, pod)\n\t\t\t}\n\n\t\t\tenvConfigMaps := o.PargeEnvFiletoConfigMaps(name, service, opt)\n\t\t\tobjects = append(objects, envConfigMaps...)\n\t\t} else {\n\t\t\tobjects = o.CreateWorkloadAndConfigMapObjects(name, service, opt)\n\n\t\t\tif opt.CreateDeploymentConfig {\n\t\t\t\tobjects = append(objects, o.initDeploymentConfig(name, service, replica)) // OpenShift DeploymentConfigs\n\t\t\t\t// create ImageStream after deployment (creating IS will trigger new deployment)\n\t\t\t\tobjects = append(objects, o.initImageStream(name, service, opt))\n\t\t\t}\n\n\t\t\t// buildconfig needs to be added to objects after imagestream because of this Openshift bug: https://github.com/openshift/origin/issues/4518\n\t\t\t// Generate BuildConfig if the parameter has been passed\n\t\t\tif service.Build != \"\" && opt.Build == \"build-config\" {\n\t\t\t\t// Get the compose file directory\n\t\t\t\tcomposeFileDir, err = transformer.GetComposeFileDir(opt.InputFiles)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Warningf(\"Error %v in detecting compose file's directory.\", err)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Check for Git\n\t\t\t\tif !HasGitBinary() && (buildRepo == \"\" || buildBranch == \"\") {\n\t\t\t\t\treturn nil, errors.New(\"Git is not installed! Please install Git to create buildconfig, else supply source repository and branch to use for build using '--build-repo', '--build-branch' options respectively\")\n\t\t\t\t}\n\n\t\t\t\t// Check the Git branch\n\t\t\t\tif buildBranch == \"\" {\n\t\t\t\t\tbuildBranch, err = GetGitCurrentBranch(composeFileDir)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, errors.Wrap(err, \"Buildconfig cannot be created because current git branch couldn't be detected.\")\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Detect the remote branches\n\t\t\t\tif opt.BuildRepo == \"\" {\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, errors.Wrap(err, \"Buildconfig cannot be created because remote for current git branch couldn't be detected.\")\n\t\t\t\t\t}\n\t\t\t\t\tbuildRepo, err = GetGitCurrentRemoteURL(composeFileDir)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, errors.Wrap(err, \"Buildconfig cannot be created because git remote origin repo couldn't be detected.\")\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Initialize and build BuildConfig\n\t\t\t\tbc, err := initBuildConfig(name, service, buildRepo, buildBranch)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, errors.Wrap(err, \"initBuildConfig failed\")\n\t\t\t\t}\n\t\t\t\tobjects = append(objects, bc) // Openshift BuildConfigs\n\n\t\t\t\t// Log what we're doing\n\t\t\t\tlog.Infof(\"Buildconfig using %s::%s as source.\", buildRepo, buildBranch)\n\t\t\t}\n\t\t}\n\n\t\tif o.PortsExist(service) {\n\t\t\tif service.ServiceType == \"LoadBalancer\" {\n\t\t\t\tsvcs := o.CreateLBService(name, service)\n\t\t\t\tfor _, svc := range svcs {\n\t\t\t\t\tsvc.Spec.ExternalTrafficPolicy = corev1.ServiceExternalTrafficPolicyType(service.ServiceExternalTrafficPolicy)\n\t\t\t\t\tobjects = append(objects, svc)\n\t\t\t\t}\n\t\t\t\tif len(svcs) > 1 {\n\t\t\t\t\tlog.Warningf(\"Create multiple service to avoid using mixed protocol in the same service when it's loadbalancer type\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsvc := o.CreateService(name, service)\n\t\t\t\tobjects = append(objects, svc)\n\n\t\t\t\tif service.ExposeService != \"\" {\n\t\t\t\t\tobjects = append(objects, o.initRoute(name, service, svc.Spec.Ports[0].Port))\n\t\t\t\t}\n\t\t\t\tif service.ServiceExternalTrafficPolicy != \"\" && svc.Spec.Type != corev1.ServiceTypeNodePort {\n\t\t\t\t\tlog.Warningf(\"External Traffic Policy is ignored for the service %v of type %v\", name, service.ServiceType)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if service.ServiceType == \"Headless\" {\n\t\t\tsvc := o.CreateHeadlessService(name, service)\n\t\t\tobjects = append(objects, svc)\n\t\t\tif service.ServiceExternalTrafficPolicy != \"\" {\n\t\t\t\tlog.Warningf(\"External Traffic Policy is ignored for the service %v of type Headless\", name)\n\t\t\t}\n\t\t}\n\n\t\terr := o.UpdateKubernetesObjects(name, service, opt, &objects)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"Error transforming Kubernetes objects\")\n\t\t}\n\n\t\tallobjects = append(allobjects, objects...)\n\t}\n\n\t// sort all object so Services are first\n\to.SortServicesFirst(&allobjects)\n\to.RemoveDupObjects(&allobjects)\n\tif komposeObject.Namespace != \"\" {\n\t\ttransformer.AssignNamespaceToObjects(&allobjects, komposeObject.Namespace)\n\t}\n\t// o.FixWorkloadVersion(&allobjects)\n\n\treturn allobjects, nil\n}\n"
  },
  {
    "path": "pkg/transformer/openshift/openshift_test.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage openshift\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/testutils\"\n\t\"github.com/kubernetes/kompose/pkg/transformer\"\n\t\"github.com/kubernetes/kompose/pkg/transformer/kubernetes\"\n\tdeployapi \"github.com/openshift/api/apps/v1\"\n\t\"github.com/pkg/errors\"\n\tapi \"k8s.io/api/core/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\nfunc newServiceConfig() kobject.ServiceConfig {\n\treturn kobject.ServiceConfig{\n\t\tContainerName: \"myfoobarname\",\n\t\tImage:         \"image\",\n\t\tEnvironment:   []kobject.EnvVar{{Name: \"env\", Value: \"value\"}},\n\t\tPort:          []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},\n\t\tCommand:       []string{\"cmd\"},\n\t\tWorkingDir:    \"dir\",\n\t\tArgs:          []string{\"arg1\", \"arg2\"},\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tNetwork:       []string{\"network1\", \"network2\"}, // not supported\n\t\tLabels:        nil,\n\t\tAnnotations:   map[string]string{\"abc\": \"def\"},\n\t\tCPUQuota:      1,                    // not supported\n\t\tCapAdd:        []string{\"cap_add\"},  // not supported\n\t\tCapDrop:       []string{\"cap_drop\"}, // not supported\n\t\tExpose:        []string{\"expose\"},   // not supported\n\t\tPrivileged:    true,\n\t\tRestart:       \"always\",\n\t\tStdin:         true,\n\t\tTty:           true,\n\t}\n}\n\nfunc newServiceConfigWithExternalTrafficPolicy() kobject.ServiceConfig {\n\tloadBalancerServiceType := string(corev1.ServiceTypeLoadBalancer)\n\treturn kobject.ServiceConfig{\n\t\tName:                         \"app\",\n\t\tPort:                         []kobject.Ports{{HostPort: 123, ContainerPort: 456}},\n\t\tServiceType:                  loadBalancerServiceType,\n\t\tServiceExternalTrafficPolicy: \"local\",\n\t}\n}\n\nfunc TestOpenShiftUpdateKubernetesObjects(t *testing.T) {\n\tt.Log(\"Test case: Testing o.UpdateKubernetesObjects()\")\n\tvar object []runtime.Object\n\to := OpenShift{}\n\tserviceConfig := newServiceConfig()\n\topt := kobject.ConvertOptions{}\n\n\tobject = append(object, o.initDeploymentConfig(\"foobar\", serviceConfig, 3))\n\to.UpdateKubernetesObjects(\"foobar\", serviceConfig, opt, &object)\n\n\tfor _, obj := range object {\n\t\tswitch tobj := obj.(type) {\n\t\tcase *deployapi.DeploymentConfig:\n\t\t\tt.Log(\"> Testing if stdin is set correctly\")\n\t\t\tif tobj.Spec.Template.Spec.Containers[0].Stdin != serviceConfig.Stdin {\n\t\t\t\tt.Errorf(\"Expected stdin to be %v, got %v instead\", serviceConfig.Stdin, tobj.Spec.Template.Spec.Containers[0].Stdin)\n\t\t\t}\n\t\t\tt.Log(\"> Testing if TTY is set correctly\")\n\t\t\tif tobj.Spec.Template.Spec.Containers[0].TTY != serviceConfig.Tty {\n\t\t\t\tt.Errorf(\"Expected TTY to be %v, got %v instead\", serviceConfig.Tty, tobj.Spec.Template.Spec.Containers[0].TTY)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestInitDeploymentConfig(t *testing.T) {\n\to := OpenShift{}\n\tspec := o.initDeploymentConfig(\"foobar\", newServiceConfig(), 1)\n\n\t// Check that \"foobar\" is used correctly as a name\n\tif spec.Spec.Template.Spec.Containers[0].Name != \"foobar\" {\n\t\tt.Errorf(\"Expected foobar for name, actual %s\", spec.Spec.Template.Spec.Containers[0].Name)\n\t}\n\n\t// Check that \"myfoobarname\" is used correctly as a ContainerName\n\tif spec.Spec.Triggers[1].ImageChangeParams.ContainerNames[0] != \"myfoobarname\" {\n\t\tt.Errorf(\"Expected myfoobarname for name, actual %s\", spec.Spec.Triggers[1].ImageChangeParams.ContainerNames[0])\n\t}\n\n\t// Check that the APIVersion is equal to \"apps.openshift.io/v1\"\n\tif spec.APIVersion != \"apps.openshift.io/v1\" {\n\t\tt.Errorf(\"Expected 'apps.openshift.io/v1' for APIVersion, actual %s\", spec.APIVersion)\n\t}\n}\n\nfunc TestKomposeConvertRoute(t *testing.T) {\n\to := OpenShift{}\n\tname := \"app\"\n\tsc := newServiceConfig()\n\tsc.ExposeService = \"true\"\n\tvar port int32 = 5555\n\troute := o.initRoute(name, sc, port)\n\n\tif route.ObjectMeta.Name != name {\n\t\tt.Errorf(\"Expected %s for name, actual %s\", name, route.ObjectMeta.Name)\n\t}\n\tif route.Spec.To.Name != name {\n\t\tt.Errorf(\"Expected %s for name, actual %s\", name, route.Spec.To.Name)\n\t}\n\tif route.Spec.Port.TargetPort.IntVal != port {\n\t\tt.Errorf(\"Expected %d for port, actual %d\", port, route.Spec.Port.TargetPort.IntVal)\n\t}\n\tif route.Spec.Host != \"\" {\n\t\tt.Errorf(\"Expected Spec.Host to not be set, got %s instead\", route.Spec.Host)\n\t}\n\n\tsc.ExposeService = \"example.com\"\n\troute = o.initRoute(name, sc, port)\n\n\tif route.Spec.Host != sc.ExposeService {\n\t\tt.Errorf(\"Expected %s for Spec.Host, actual %s\", sc.ExposeService, route.Spec.Host)\n\t}\n}\n\n// Test getting git remote url for a directory\nfunc TestGetGitRemote(t *testing.T) {\n\tvar output string\n\tvar err error\n\n\tgitDir := testutils.CreateLocalGitDirectory(t)\n\ttestutils.SetGitRemote(t, gitDir, \"newremote\", \"https://git.test.com/somerepo\")\n\ttestutils.CreateGitRemoteBranch(t, gitDir, \"newbranch\", \"newremote\")\n\tdir := testutils.CreateLocalDirectory(t)\n\tdefer os.RemoveAll(gitDir)\n\tdefer os.RemoveAll(dir)\n\n\ttestCases := map[string]struct {\n\t\texpectError bool\n\t\tdir         string\n\t\tbranch      string\n\t\toutput      string\n\t}{\n\t\t\"Get git remote for branch success\":   {false, gitDir, \"newbranch\", \"https://git.test.com/somerepo.git\"},\n\t\t\"Get git remote error in non git dir\": {true, dir, \"\", \"\"},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case: \", name)\n\t\toutput, err = GetGitCurrentRemoteURL(test.dir)\n\n\t\tif test.expectError {\n\t\t\tif err == nil {\n\t\t\t\tt.Errorf(\"Expected error, got success instead!\")\n\t\t\t}\n\t\t} else {\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Expected success, got error: %v\", err)\n\t\t\t}\n\t\t\tif output != test.output {\n\t\t\t\tt.Errorf(\"Expected: %#v, got: %#v\", test.output, output)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Test getting current git branch in a directory\nfunc TestGitGetCurrentBranch(t *testing.T) {\n\tvar output string\n\tvar err error\n\n\tgitDir := testutils.CreateLocalGitDirectory(t)\n\ttestutils.SetGitRemote(t, gitDir, \"newremote\", \"https://git.test.com/somerepo\")\n\ttestutils.CreateGitRemoteBranch(t, gitDir, \"newbranch\", \"newremote\")\n\tdir := testutils.CreateLocalDirectory(t)\n\tdefer os.RemoveAll(gitDir)\n\tdefer os.RemoveAll(dir)\n\n\ttestCases := map[string]struct {\n\t\texpectError bool\n\t\tdir         string\n\t\toutput      string\n\t}{\n\t\t\"Get git current branch success\": {false, gitDir, \"newbranch\"},\n\t\t\"Get git current branch error\":   {true, dir, \"\"},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case: \", name)\n\t\toutput, err = GetGitCurrentBranch(test.dir)\n\n\t\tif test.expectError {\n\t\t\tif err == nil {\n\t\t\t\tt.Error(\"Expected error, got success instead!\")\n\t\t\t}\n\t\t} else {\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Expected success, got error: %v\", err)\n\t\t\t}\n\t\t\tif output != test.output {\n\t\t\t\tt.Errorf(\"Expected: %#v, got: %#v\", test.output, output)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Test getting compose file directory path: relative to project dir or absolute path\nfunc TestGetComposeFileDir(t *testing.T) {\n\tvar output string\n\tvar err error\n\twd, _ := os.Getwd()\n\n\ttestCases := map[string]struct {\n\t\tinputFiles []string\n\t\toutput     string\n\t}{\n\t\t\"Get compose file dir for relative input file path\": {[]string{\"foo/bar.yaml\"}, filepath.Join(wd, \"foo\")},\n\t\t\"Get compose file dir for abs input file path\":      {[]string{\"/abs/path/to/compose.yaml\"}, \"/abs/path/to\"},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case: \", name)\n\n\t\toutput, err = transformer.GetComposeFileDir(test.inputFiles)\n\n\t\tif err != nil {\n\t\t\tt.Errorf(\"Expected success, got error: %#v\", err)\n\t\t}\n\n\t\tif output != test.output {\n\t\t\tt.Errorf(\"Expected output: %#v, got: %#v\", test.output, output)\n\t\t}\n\t}\n}\n\n// Test getting build context relative to project's root dir\nfunc TestGetAbsBuildContext(t *testing.T) {\n\tvar output string\n\tvar err error\n\n\tgitDir := testutils.CreateLocalGitDirectory(t)\n\ttestutils.SetGitRemote(t, gitDir, \"newremote\", \"https://git.test.com/somerepo\")\n\ttestutils.CreateGitRemoteBranch(t, gitDir, \"newbranch\", \"newremote\")\n\ttestutils.CreateSubdir(t, gitDir, \"a/b/build\")\n\ttestutils.CreateSubdir(t, gitDir, \"build\")\n\tdir := testutils.CreateLocalDirectory(t)\n\tdefer os.RemoveAll(gitDir)\n\tdefer os.RemoveAll(dir)\n\n\ttestCases := map[string]struct {\n\t\texpectError bool\n\t\tcontext     string\n\t\toutput      string\n\t}{\n\t\t\"Get abs build context success case-1\": {false, filepath.Join(gitDir, \"a/b/build\"), \"a/b/build/\"},\n\t\t\"Get abs build context success case-2\": {false, filepath.Join(gitDir, \"build\"), \"build/\"},\n\t\t\"Get abs build context error case-1\":   {true, \"example/build\", \"example/build/\"},\n\t\t\"Get abs build context error case-2\":   {true, \"/tmp\", \"\"},\n\t}\n\n\tfor name, test := range testCases {\n\t\tt.Log(\"Test case: \", name)\n\t\toutput, err = GetAbsBuildContext(test.context)\n\n\t\tif test.expectError {\n\t\t\tif err == nil {\n\t\t\t\tt.Errorf(\"Expected error, got success instead!\")\n\t\t\t}\n\t\t} else {\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Expected success, got error: %v\", err)\n\t\t\t}\n\t\t\tif output != test.output {\n\t\t\t\tt.Errorf(\"Expected: %#v, got: %#v\", test.output, output)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Test initializing buildconfig for a service\nfunc TestInitBuildConfig(t *testing.T) {\n\tserviceName := \"serviceA\"\n\trepo := \"https://git.test.com/org/repo1\"\n\tbranch := \"somebranch\"\n\tbuildArgs := []corev1.EnvVar{{Name: \"name\", Value: \"value\"}}\n\tvalue := \"value\"\n\ttestDir := \"a/build\"\n\n\tdir := testutils.CreateLocalGitDirectory(t)\n\ttestutils.CreateSubdir(t, dir, testDir)\n\tdefer os.RemoveAll(dir)\n\n\ttestCases := []struct {\n\t\tName          string\n\t\tServiceConfig kobject.ServiceConfig\n\t}{\n\t\t{\n\t\t\tName: \"Service config without image key\",\n\t\t\tServiceConfig: kobject.ServiceConfig{\n\t\t\t\tBuild:      filepath.Join(dir, testDir),\n\t\t\t\tDockerfile: \"Dockerfile-alternate\",\n\t\t\t\tBuildArgs:  map[string]*string{\"name\": &value},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Service config with image key\",\n\t\t\tServiceConfig: kobject.ServiceConfig{\n\t\t\t\tBuild:      filepath.Join(dir, testDir),\n\t\t\t\tDockerfile: \"Dockerfile-alternate\",\n\t\t\t\tBuildArgs:  map[string]*string{\"name\": &value},\n\t\t\t\tImage:      \"foo:bar\",\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range testCases {\n\t\tbc, err := initBuildConfig(serviceName, test.ServiceConfig, repo, branch)\n\t\tif err != nil {\n\t\t\tt.Error(errors.Wrap(err, \"initBuildConfig failed\"))\n\t\t}\n\n\t\tassertions := map[string]struct {\n\t\t\tfield string\n\t\t\tvalue string\n\t\t}{\n\t\t\t\"Assert buildconfig source git URI\":     {bc.Spec.CommonSpec.Source.Git.URI, repo},\n\t\t\t\"Assert buildconfig source git Ref\":     {bc.Spec.CommonSpec.Source.Git.Ref, branch},\n\t\t\t\"Assert buildconfig source context dir\": {bc.Spec.CommonSpec.Source.ContextDir, testDir + \"/\"},\n\t\t\t// BuildConfig output image is named after service name. If image key is set than tag from that is used.\n\t\t\t\"Assert buildconfig output name\":    {bc.Spec.CommonSpec.Output.To.Name, serviceName + \":\" + GetImageTag(test.ServiceConfig.Image)},\n\t\t\t\"Assert buildconfig dockerfilepath\": {bc.Spec.CommonSpec.Strategy.DockerStrategy.DockerfilePath, test.ServiceConfig.Dockerfile},\n\t\t}\n\n\t\tfor name, assertionTest := range assertions {\n\t\t\tif assertionTest.field != assertionTest.value {\n\t\t\t\tt.Errorf(\"%s Expected: %#v, got: %#v\", name, assertionTest.value, assertionTest.field)\n\t\t\t}\n\t\t}\n\t\tif !reflect.DeepEqual(bc.Spec.CommonSpec.Strategy.DockerStrategy.Env, buildArgs) {\n\t\t\tt.Errorf(\"Expected: %#v, got: %#v\", bc.Spec.CommonSpec.Strategy.DockerStrategy.Env, buildArgs)\n\t\t}\n\t}\n}\n\n// TestServiceWithoutPort this tests if Headless Service is created for services without Port (with label)\nfunc TestServiceWithoutPort(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tServiceType:   \"Headless\",\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\to := OpenShift{Kubernetes: kubernetes.Kubernetes{}}\n\n\tobjects, err := o.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"o.Transform failed\"))\n\t}\n\tif err := testutils.CheckForHeadless(objects); err != nil {\n\t\tt.Error(err)\n\t}\n}\n\nfunc TestRestartOnFailure(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tRestart: \"on-failure\",\n\t}\n\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\n\t// define all test cases for RestartOnFailure function\n\treplicas := 2\n\ttestCase := map[string]struct {\n\t\tkomposeObject kobject.KomposeObject\n\t\topt           kobject.ConvertOptions\n\t}{\n\t\t// objects generated are deployment, service and replication controller\n\t\t\"Do not Create DeploymentConfig (DC) with restart:'on-failure'\": {komposeObject, kobject.ConvertOptions{IsDeploymentConfigFlag: true, Replicas: replicas}},\n\t}\n\n\tfor name, test := range testCase {\n\t\tt.Log(\"Test case:\", name)\n\t\to := OpenShift{}\n\n\t\t_, err := o.Transform(test.komposeObject, test.opt)\n\t\tif err == nil {\n\t\t\tt.Errorf(\"Expected an error, got %v instead\", err)\n\t\t}\n\t}\n}\n\n// Tests if deployment strategy is being set to Recreate when volumes are\n// present\nfunc TestRecreateStrategyWithVolumesPresent(t *testing.T) {\n\tservice := kobject.ServiceConfig{\n\t\tContainerName: \"name\",\n\t\tImage:         \"image\",\n\t\tVolList:       []string{\"/tmp/volume\"},\n\t\tVolumes:       []kobject.Volumes{{SvcName: \"app\", MountPath: \"/tmp/volume\", PVCName: \"app-claim0\"}},\n\t}\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": service},\n\t}\n\n\to := OpenShift{Kubernetes: kubernetes.Kubernetes{}}\n\n\tobjects, err := o.Transform(komposeObject, kobject.ConvertOptions{CreateDeploymentConfig: true, Replicas: 1})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"o.Transform failed\"))\n\t}\n\tfor _, obj := range objects {\n\t\tif deploymentConfig, ok := obj.(*deployapi.DeploymentConfig); ok {\n\t\t\tif deploymentConfig.Spec.Strategy.Type != deployapi.DeploymentStrategyTypeRecreate {\n\t\t\t\tt.Errorf(\"Expected %v as Strategy Type, got %v\",\n\t\t\t\t\tdeployapi.DeploymentStrategyTypeRecreate,\n\t\t\t\t\tdeploymentConfig.Spec.Strategy.Type)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestServiceExternalTrafficPolicy(t *testing.T) {\n\tgroupName := \"pod_group\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfigWithExternalTrafficPolicy()},\n\t}\n\to := OpenShift{}\n\tobjs, err := o.Transform(komposeObject, kobject.ConvertOptions{ServiceGroupMode: groupName})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif service, ok := obj.(*corev1.Service); ok {\n\t\t\tserviceExternalTrafficPolicy := string(service.Spec.ExternalTrafficPolicy)\n\t\t\tif serviceExternalTrafficPolicy != strings.ToLower(string(corev1.ServiceExternalTrafficPolicyTypeLocal)) {\n\t\t\t\tt.Errorf(\"Expected Local as external lifecycle policy, got %v\", serviceExternalTrafficPolicy)\n\t\t\t}\n\t\t\tserviceType := service.Spec.Type\n\t\t\tif serviceType != corev1.ServiceTypeLoadBalancer {\n\t\t\t\tt.Errorf(\"Expected LoadBalancer as service type, got %v\", serviceType)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestNamespaceGeneration(t *testing.T) {\n\tns := \"app\"\n\tkomposeObject := kobject.KomposeObject{\n\t\tServiceConfigs: map[string]kobject.ServiceConfig{\"app\": newServiceConfig()},\n\t\tNamespace:      ns,\n\t}\n\to := OpenShift{}\n\tobjs, err := o.Transform(komposeObject, kobject.ConvertOptions{})\n\tif err != nil {\n\t\tt.Error(errors.Wrap(err, \"k.Transform failed\"))\n\t}\n\tfor _, obj := range objs {\n\t\tif namespace, ok := obj.(*api.Namespace); ok {\n\t\t\tif strings.ToLower(ns) != strings.ToLower(namespace.ObjectMeta.Name) {\n\t\t\t\tt.Errorf(\"Expected namespace name %v, got %v\", ns, namespace.ObjectMeta.Name)\n\t\t\t}\n\t\t}\n\t\tif dep, ok := obj.(*deployapi.DeploymentConfig); ok {\n\t\t\tif dep.ObjectMeta.Namespace != ns {\n\t\t\t\tt.Errorf(\"Expected deployment namespace %v, got %v\", ns, dep.ObjectMeta.Namespace)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/transformer/openshift/utils.go",
    "content": "package openshift\n\nimport (\n\t\"github.com/pkg/errors\"\n\t\"os/exec\"\n\t\"strings\"\n)\n\n// GetImageTag get tag name from image name\n// if no tag is specified return 'latest'\nfunc GetImageTag(image string) string {\n\t// format:      registry_host:registry_port/repo_name/image_name:image_tag\n\t// example:\n\t// 1)     myregistryhost:5000/fedora/httpd:version1.0\n\t// 2)     myregistryhost:5000/fedora/httpd\n\t// 3)     myregistryhost/fedora/httpd:version1.0\n\t// 4)     myregistryhost/fedora/httpd\n\t// 5)     fedora/httpd\n\t// 6)     httpd\n\timageAndTag := image\n\n\ti := strings.Split(image, \"/\")\n\tif len(i) >= 2 {\n\t\timageAndTag = i[len(i)-1]\n\t}\n\n\tp := strings.Split(imageAndTag, \":\")\n\tif len(p) == 2 {\n\t\treturn p[1]\n\t}\n\treturn \"latest\"\n}\n\n// GetAbsBuildContext returns build context relative to project root dir\nfunc GetAbsBuildContext(context string) (string, error) {\n\tcmd := exec.Command(\"git\", \"rev-parse\", \"--show-prefix\")\n\tcmd.Dir = context\n\tvar out strings.Builder\n\tvar stderr strings.Builder\n\tcmd.Stdout = &out\n\tcmd.Stderr = &stderr\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn \"\", errors.New(stderr.String())\n\t}\n\t//convert output of command to string\n\tcontextDir := strings.Trim(out.String(), \"\\n\")\n\treturn contextDir, nil\n}\n\n// HasGitBinary checks if the 'git' binary is available on the system\nfunc HasGitBinary() bool {\n\t_, err := exec.LookPath(\"git\")\n\treturn err == nil\n}\n\n// GetGitCurrentRemoteURL gets current git remote URI for the current git repo\nfunc GetGitCurrentRemoteURL(composeFileDir string) (string, error) {\n\tcmd := exec.Command(\"git\", \"ls-remote\", \"--get-url\")\n\tcmd.Dir = composeFileDir\n\tvar out strings.Builder\n\tvar stderr strings.Builder\n\tcmd.Stdout = &out\n\tcmd.Stderr = &stderr\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn \"\", errors.New(stderr.String())\n\t}\n\turl := strings.TrimRight(out.String(), \"\\n\")\n\tif !strings.HasSuffix(url, \".git\") {\n\t\turl += \".git\"\n\t}\n\treturn url, nil\n}\n\n// GetGitCurrentBranch gets current git branch name for the current git repo\nfunc GetGitCurrentBranch(composeFileDir string) (string, error) {\n\tcmd := exec.Command(\"git\", \"rev-parse\", \"--abbrev-ref\", \"HEAD\")\n\tcmd.Dir = composeFileDir\n\tvar out strings.Builder\n\tvar stderr strings.Builder\n\tcmd.Stdout = &out\n\tcmd.Stderr = &stderr\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn \"\", errors.New(stderr.String())\n\t}\n\treturn strings.TrimRight(out.String(), \"\\n\"), nil\n}\n"
  },
  {
    "path": "pkg/transformer/transformer.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage transformer\n\nimport (\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// Transformer interface  defines transformer that is converting kobject to other resources\ntype Transformer interface {\n\t// Transform converts KomposeObject to transformer specific objects.\n\tTransform(kobject.KomposeObject, kobject.ConvertOptions) ([]runtime.Object, error)\n}\n"
  },
  {
    "path": "pkg/transformer/utils.go",
    "content": "/*\nCopyright 2017 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    http://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*/\n\npackage transformer\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\tdockerlib \"github.com/fsouza/go-dockerclient\"\n\t\"github.com/kubernetes/kompose/pkg/kobject\"\n\t\"github.com/kubernetes/kompose/pkg/utils/docker\"\n\t\"github.com/kubernetes/kompose/pkg/version\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n\tapi \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// Selector used as labels and selector\nconst Selector = \"io.kompose.service\"\n\n// Exists returns true if a file path exists.\n// Otherwise, returns false.\nfunc Exists(p string) bool {\n\t_, err := os.Stat(p)\n\treturn err == nil\n}\n\n// CreateOutFile creates the file to write to if --out is specified\nfunc CreateOutFile(out string) (*os.File, error) {\n\tif len(out) == 0 {\n\t\treturn nil, nil\n\t}\n\t// Creates directories if \"out\" contains nonexistent directories.\n\tif dir := filepath.Dir(out); !Exists(dir) {\n\t\tif err := os.MkdirAll(dir, os.ModePerm); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"failed to create directories\")\n\t\t}\n\t}\n\tf, err := os.Create(out)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to create file, os.Create failed\")\n\t}\n\treturn f, nil\n}\n\n// ParseVolume parses a given volume, which might be [name:][host:]container[:access_mode]\nfunc ParseVolume(volume string) (name, host, container, mode string, err error) {\n\tif containWindowsPath(volume) {\n\t\treturn parseWindowsVolume(volume)\n\t}\n\treturn parseVolume(volume)\n}\n\nfunc parseVolume(volume string) (name, host, container, mode string, err error) {\n\tseparator := \":\"\n\n\t// Parse based on \":\"\n\tvolumeStrings := strings.Split(volume, separator)\n\tif len(volumeStrings) == 0 {\n\t\treturn\n\t}\n\n\t// Set name if existed\n\tif !isPath(volumeStrings[0]) {\n\t\tname = volumeStrings[0]\n\t\tvolumeStrings = volumeStrings[1:]\n\t}\n\n\t// Check if *anything* has been passed\n\tif len(volumeStrings) == 0 {\n\t\terr = fmt.Errorf(\"invalid volume format: %s\", volume)\n\t\treturn\n\t}\n\n\t// Get the last \":\" passed which is presumingly the \"access mode\"\n\tpossibleAccessMode := volumeStrings[len(volumeStrings)-1]\n\n\t// Check to see if :Z or :z exists. We do not support SELinux relabeling at the moment.\n\t// See https://github.com/kubernetes/kompose/issues/176\n\t// Otherwise, check to see if \"rw\" or \"ro\" has been passed\n\tif possibleAccessMode == \"z\" || possibleAccessMode == \"Z\" {\n\t\tlog.Warnf(\"Volume mount \\\"%s\\\" will be mounted without labeling support. :z or :Z not supported\", volume)\n\t\tmode = \"\"\n\t\tvolumeStrings = volumeStrings[:len(volumeStrings)-1]\n\t} else if possibleAccessMode == \"rw\" || possibleAccessMode == \"ro\" {\n\t\tmode = possibleAccessMode\n\t\tvolumeStrings = volumeStrings[:len(volumeStrings)-1]\n\t}\n\n\t// Check the volume format as well as host\n\tcontainer = volumeStrings[len(volumeStrings)-1]\n\tvolumeStrings = volumeStrings[:len(volumeStrings)-1]\n\tif len(volumeStrings) == 1 {\n\t\thost = volumeStrings[0]\n\t}\n\tif !isPath(container) || (len(host) > 0 && !isPath(host)) || len(volumeStrings) > 1 {\n\t\terr = fmt.Errorf(\"invalid volume format: %s\", volume)\n\t\treturn\n\t}\n\treturn\n}\n\n// parseWindowsVolume parses window volume.\n// example: windows host mount to windows container\n// volume = dataVolumeName:C:\\Users\\Data:D:\\config:rw\n// it can be parsed:\n// name=dataVolumeName, host=C:\\Users\\Data, container=D:\\config, mode=rw\n// example: windows host mount to linux container\n// volume = dataVolumeName:C:\\Users\\Data:/etc/config:rw\n// it can be parsed:\n// name=dataVolumeName, host=C:\\Users\\Data, container=/etc/config, mode=rw\nfunc parseWindowsVolume(volume string) (name, host, container, mode string, err error) {\n\tvar (\n\t\tbuffer, volumePaths []string\n\t\tvolumeStrings       = strings.Split(volume, \":\")\n\t)\n\n\t// extract path and leave order\n\tfor _, fragment := range volumeStrings {\n\t\tswitch {\n\t\tcase containWindowsPath(fragment):\n\t\t\tif len(buffer) == 0 {\n\t\t\t\terr = fmt.Errorf(\"invalid windows volume %s\", volume)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tdriveLetter := buffer[len(buffer)-1]\n\t\t\tif len(driveLetter) != 1 {\n\t\t\t\terr = fmt.Errorf(\"invalid windows volume %s\", volume)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvolumePaths = append(volumePaths, driveLetter+\":\"+fragment)\n\t\t\tbuffer = buffer[:len(buffer)-1]\n\n\t\tcase isPath(fragment):\n\t\t\tvolumePaths = append(volumePaths, fragment)\n\t\tdefault:\n\t\t\tbuffer = append(buffer, fragment)\n\t\t}\n\t}\n\n\t// set name and mode if exist\n\tif len(buffer) == 1 {\n\t\tif volumeStrings[0] == buffer[0] {\n\t\t\tname = buffer[0]\n\t\t} else if volumeStrings[len(volumeStrings)-1] == buffer[0] {\n\t\t\tmode = buffer[0]\n\t\t}\n\t} else if len(buffer) == 2 {\n\t\tname = buffer[0]\n\t\tmode = buffer[1]\n\t} else if len(buffer) > 2 {\n\t\terr = fmt.Errorf(\"invalid windows volume %s\", volume)\n\t\treturn\n\t}\n\n\t// Support in pass time\n\t// Check to see if :Z or :z exists. We do not support SELinux relabeling at the moment.\n\t// See https://github.com/kubernetes/kompose/issues/176\n\t// Otherwise, check to see if \"rw\" or \"ro\" has been passed\n\tif mode == \"z\" || mode == \"Z\" {\n\t\tlog.Warnf(\"Volume mount \\\"%s\\\" will be mounted without labeling support. :z or :Z not supported\", volume)\n\t\tmode = \"\"\n\t}\n\n\t// Set host and container if exist\n\tif len(volumePaths) == 1 {\n\t\tcontainer = volumePaths[0]\n\t} else if len(volumePaths) == 2 {\n\t\thost = volumePaths[0]\n\t\tcontainer = volumePaths[1]\n\t} else {\n\t\terr = fmt.Errorf(\"invalid windows volume %s\", volume)\n\t\treturn\n\t}\n\treturn\n}\n\n// containWindowsPath check whether it contains windows path.\n// windows path's separator is \"\\\"\nfunc containWindowsPath(substring string) bool {\n\treturn strings.Contains(substring, \"\\\\\")\n}\n\n// ParseIngressPath parse path for ingress.\n// eg. example.com/org -> example.com org\nfunc ParseIngressPath(url string) (string, string) {\n\tif strings.Contains(url, \"/\") {\n\t\tsplits := strings.Split(url, \"/\")\n\t\treturn splits[0], \"/\" + strings.Join(splits[1:], \"/\")\n\t}\n\treturn url, \"\"\n}\n\nfunc isPath(substring string) bool {\n\treturn strings.Contains(substring, \"/\") || substring == \".\"\n}\n\n// ConfigLabels configures label name alone\nfunc ConfigLabels(name string) map[string]string {\n\treturn map[string]string{Selector: name}\n}\n\n// ConfigLabelsWithNetwork configures label and add Network Information in labels\nfunc ConfigLabelsWithNetwork(name string, net []string) map[string]string {\n\tlabels := map[string]string{}\n\tlabels[Selector] = name\n\n\tfor _, n := range net {\n\t\tlabels[\"io.kompose.network/\"+n] = \"true\"\n\t}\n\treturn labels\n\t//return map[string]string{Selector: name, \"Network\": net}\n}\n\n// ConfigAllLabels creates labels with service nam and deploy labels\nfunc ConfigAllLabels(name string, service *kobject.ServiceConfig) map[string]string {\n\tbase := ConfigLabels(name)\n\tif service.DeployLabels != nil {\n\t\tfor k, v := range service.DeployLabels {\n\t\t\tbase[k] = v\n\t\t}\n\t}\n\treturn base\n}\n\n// ConfigAnnotations configures annotations\nfunc ConfigAnnotations(service kobject.ServiceConfig) map[string]string {\n\tannotations := map[string]string{}\n\n\tfor key, value := range service.Annotations {\n\t\tannotations[key] = value\n\t}\n\n\tannotations[\"kompose.cmd\"] = strings.Join(os.Args, \" \")\n\tversionCmd := exec.Command(\"kompose\", \"version\")\n\tout, err := versionCmd.Output()\n\tif err != nil {\n\t\terrors.Wrap(err, \"Failed to get kompose version\")\n\t}\n\tannotations[\"kompose.version\"] = strings.Trim(string(out), \" \\n\")\n\n\t// If the version is blank (couldn't retrieve the kompose version for whatever reason)\n\tif annotations[\"kompose.version\"] == \"\" {\n\t\tannotations[\"kompose.version\"] = version.VERSION + \" (\" + version.GITCOMMIT + \")\"\n\t}\n\n\t// if service.WithKomposeAnnotation = false, we remove **all** kompose annotations (io.kompose.*)\n\tif !service.WithKomposeAnnotation {\n\t\tfor key := range annotations {\n\t\t\tif strings.HasPrefix(key, \"kompose.\") {\n\t\t\t\tdelete(annotations, key)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn annotations\n}\n\n// Print either prints to stdout or to file/s\nfunc Print(name, path string, trailing string, data []byte, toStdout, generateJSON bool, f *os.File, provider string) (string, error) {\n\tfile := \"\"\n\t// TODO: we should refactor / change this hack in the future once we have a better solution\n\tre := regexp.MustCompile(`(?s)status:\\n.*`)\n\tdata = re.ReplaceAll(data, nil)\n\tif generateJSON {\n\t\tfile = fmt.Sprintf(\"%s-%s.json\", name, trailing)\n\t} else {\n\t\tfile = fmt.Sprintf(\"%s-%s.yaml\", name, trailing)\n\t}\n\tif toStdout {\n\t\tfmt.Fprintf(os.Stdout, \"%s\\n\", string(data))\n\t\treturn \"\", nil\n\t} else if f != nil {\n\t\t// Write all content to a single file f\n\t\tif _, err := f.WriteString(fmt.Sprintf(\"%s\\n\", string(data))); err != nil {\n\t\t\treturn \"\", errors.Wrap(err, \"f.WriteString failed, Failed to write %s to file: \"+trailing)\n\t\t}\n\t\tf.Sync()\n\t} else {\n\t\t// Write content separately to each file\n\t\tfile = filepath.Join(path, file)\n\t\tif err := os.WriteFile(file, data, 0644); err != nil {\n\t\t\treturn \"\", errors.Wrap(err, \"Failed to write %s: \"+trailing)\n\t\t}\n\t\tlog.Printf(\"%s file %q created\", formatProviderName(provider), file)\n\t}\n\treturn file, nil\n}\n\n// If Openshift, change to OpenShift!\nfunc formatProviderName(provider string) string {\n\tif strings.EqualFold(provider, \"openshift\") {\n\t\treturn \"OpenShift\"\n\t} else if strings.EqualFold(provider, \"kubernetes\") {\n\t\treturn \"Kubernetes\"\n\t}\n\treturn provider\n}\n\n// EnvSort struct\ntype EnvSort []api.EnvVar\n\n// Len returns the number of elements in the collection.\nfunc (env EnvSort) Len() int {\n\treturn len(env)\n}\n\n// Less returns whether the element with index i should sort before\n// the element with index j.\nfunc (env EnvSort) Less(i, j int) bool {\n\treturn env[i].Name < env[j].Name\n}\n\n// Swap swaps the elements with indexes i and j.\nfunc (env EnvSort) Swap(i, j int) {\n\tenv[i], env[j] = env[j], env[i]\n}\n\n// GetComposeFileDir returns compose file directory\nfunc GetComposeFileDir(inputFiles []string) (string, error) {\n\t// Check if input files are specified\n\tif len(inputFiles) <= 0 {\n\t\treturn \"\", errors.New(\"No input files specified\")\n\t}\n\n\t// Lets assume all the docker-compose files are in the same directory\n\tinputFile, err := filepath.Abs(inputFiles[0])\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tlog.Debugf(\"Compose file dir: %s\", filepath.Dir(inputFile))\n\treturn filepath.Dir(inputFile), nil\n}\n\n// BuildDockerImage builds docker image\nfunc BuildDockerImage(service kobject.ServiceConfig, name string) error {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Debug(\"Build image working dir is: \", wd)\n\n\tlog.Debug(\"Build image service build is: \", service.Build)\n\t// Get the appropriate image source and name\n\timagePath := service.Build\n\tif !path.IsAbs(service.Build) {\n\t\timagePath = path.Join(wd, service.Build)\n\t}\n\tlog.Debugf(\"Build image context is: %s\", imagePath)\n\n\tif _, err := os.Stat(imagePath); err != nil {\n\t\treturn errors.Wrapf(err, \"%s is not a valid path for building image %s. Check if this dir exists.\", service.Build, name)\n\t}\n\n\timageName := name\n\tif service.Image != \"\" {\n\t\timageName = service.Image\n\t}\n\n\tbuildargs := []dockerlib.BuildArg{}\n\tfor envName, envValue := range service.BuildArgs {\n\t\tvar value string\n\t\tif envValue == nil {\n\t\t\tvalue = os.Getenv(envName)\n\t\t} else {\n\t\t\tvalue = *envValue\n\t\t}\n\t\tbuildargs = append(buildargs, dockerlib.BuildArg{Name: envName, Value: value})\n\t}\n\n\t// Connect to the Docker client\n\tclient, err := docker.Client()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Use the build struct function to build the image\n\t// Build the image!\n\tbuild := docker.Build{Client: *client}\n\terr = build.BuildImage(imagePath, imageName, service.Dockerfile, buildargs, service.BuildTarget)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// PushDockerImageWithOpt pushes docker image\nfunc PushDockerImageWithOpt(service kobject.ServiceConfig, serviceName string, opt kobject.ConvertOptions) error {\n\tif !opt.PushImage {\n\t\t// Don't do anything if registry is specified but push is disabled, just WARN about it\n\t\tif opt.PushImageRegistry != \"\" {\n\t\t\tlog.Warnf(\"Push image registry '%s' is specified but push image is disabled, skipping pushing to repository\", opt.PushImageRegistry)\n\t\t}\n\t\treturn nil\n\t}\n\n\tlog.Infof(\"Push image is enabled. Attempting to push image '%s'\", service.Image)\n\n\t// Don't do anything if service.Image is blank, but at least WARN about it\n\t// else, let's push the image\n\tif service.Image == \"\" {\n\t\tlog.Warnf(\"No image name has been passed for service %s, skipping pushing to repository\", serviceName)\n\t\treturn nil\n\t}\n\n\timage, err := docker.ParseImage(service.Image, opt.PushImageRegistry)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tclient, err := docker.Client()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif opt.PushImageRegistry != \"\" {\n\t\tlog.Info(\"Push image registry is specified. Tag the image into registry firstly.\")\n\t\ttag := docker.Tag{Client: *client}\n\t\terr = tag.TagImage(image)\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tpush := docker.Push{Client: *client}\n\terr = push.PushImage(image)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// CreateNamespace creates a Kubernetes namespace, which can be used in both:\n// Openshift and Kubernetes\nfunc CreateNamespace(namespace string) *api.Namespace {\n\treturn &api.Namespace{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       \"Namespace\",\n\t\t\tAPIVersion: \"v1\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: namespace,\n\t\t},\n\t}\n}\n\n// AssignNamespaceToObjects will add the namespace metadata to each object\nfunc AssignNamespaceToObjects(objs *[]runtime.Object, namespace string) {\n\tns := \"default\"\n\tif namespace != \"\" {\n\t\tns = namespace\n\t}\n\tvar result []runtime.Object\n\tfor _, obj := range *objs {\n\t\tif us, ok := obj.(metav1.Object); ok {\n\t\t\tus.SetNamespace(ns)\n\t\t}\n\t\tresult = append(result, obj)\n\t}\n\t*objs = result\n}\n"
  },
  {
    "path": "pkg/transformer/utils_test.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    http://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*/\n\npackage transformer\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestFormatProviderName(t *testing.T) {\n\tif formatProviderName(\"openshift\") != \"OpenShift\" {\n\t\tt.Errorf(\"Got %s, expected OpenShift\", formatProviderName(\"openshift\"))\n\t}\n\tif formatProviderName(\"kubernetes\") != \"Kubernetes\" {\n\t\tt.Errorf(\"Got %s, expected Kubernetes\", formatProviderName(\"kubernetes\"))\n\t}\n}\n\n// When passing \"z\" or \"Z\" we expect \"\" back.\nfunc TestZParseVolumeLabeling(t *testing.T) {\n\ttestCase := \"/foobar:/foobar:Z\"\n\twindowVolumeTestCase := \"C:\\\\foobar:/foobar:Z\"\n\t_, _, _, mode, err := ParseVolume(testCase)\n\tif err != nil {\n\t\tt.Errorf(\"In test case %q, returned unexpected error %v\", testCase, err)\n\t}\n\tif mode != \"\" {\n\t\tt.Errorf(\"In test case %q, returned mode %s, expected \\\"\\\"\", testCase, mode)\n\t}\n\n\t_, _, _, mode, err = ParseVolume(windowVolumeTestCase)\n\tif err != nil {\n\t\tt.Errorf(\"In test case %q, returned unexpected error %v\", windowVolumeTestCase, err)\n\t}\n\tif mode != \"\" {\n\t\tt.Errorf(\"In test case %q, returned mode %s, expected \\\"\\\"\", windowVolumeTestCase, mode)\n\t}\n}\n\nfunc TestParseWindowsVolumeMountLinuxContainer(t *testing.T) {\n\tname := \"datavolume\"\n\twindowsHosts := \"C:\\\\Users\"\n\tlinuxContainer := \"/etc/configs/\"\n\tmode := \"rw\"\n\n\ttests := []struct {\n\t\ttest, volume, name, host, container, mode string\n\t}{\n\t\t{\n\t\t\t\"name:host:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s:%s\", name, windowsHosts, linuxContainer, mode),\n\t\t\tname,\n\t\t\twindowsHosts,\n\t\t\tlinuxContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"host:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", windowsHosts, linuxContainer, mode),\n\t\t\t\"\",\n\t\t\twindowsHosts,\n\t\t\tlinuxContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", name, linuxContainer, mode),\n\t\t\tname,\n\t\t\t\"\",\n\t\t\tlinuxContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:host:container\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", name, windowsHosts, linuxContainer),\n\t\t\tname,\n\t\t\twindowsHosts,\n\t\t\tlinuxContainer,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"host:container\",\n\t\t\tfmt.Sprintf(\"%s:%s\", windowsHosts, linuxContainer),\n\t\t\t\"\",\n\t\t\twindowsHosts,\n\t\t\tlinuxContainer,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s\", linuxContainer, mode),\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\tlinuxContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:container\",\n\t\t\tfmt.Sprintf(\"%s:%s\", name, linuxContainer),\n\t\t\tname,\n\t\t\t\"\",\n\t\t\tlinuxContainer,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"container\",\n\t\t\tlinuxContainer,\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\tlinuxContainer,\n\t\t\t\"\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tname, host, container, mode, err := ParseVolume(test.volume)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"In test case %q, returned unexpected error %v\", test.test, err)\n\t\t}\n\t\tif name != test.name {\n\t\t\tt.Errorf(\"In test case %q, returned volume name %s, expected %s\", test.test, name, test.name)\n\t\t}\n\t\tif host != test.host {\n\t\t\tt.Errorf(\"In test case %q, returned host path %s, expected %s\", test.test, host, test.host)\n\t\t}\n\t\tif container != test.container {\n\t\t\tt.Errorf(\"In test case %q, returned container path %s, expected %s\", test.test, container, test.container)\n\t\t}\n\t\tif mode != test.mode {\n\t\t\tt.Errorf(\"In test case %q, returned access mode %s, expected %s\", test.test, mode, test.mode)\n\t\t}\n\t}\n}\n\nfunc TestParseWindowsVolumeMountWindowsContainer(t *testing.T) {\n\tname := \"datavolume\"\n\twindowsHosts := \"C:\\\\Users\"\n\twindowsContainer := \"D:\\\\Users\"\n\tmode := \"rw\"\n\n\ttests := []struct {\n\t\ttest, volume, name, host, container, mode string\n\t}{\n\t\t{\n\t\t\t\"name:host:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s:%s\", name, windowsHosts, windowsContainer, mode),\n\t\t\tname,\n\t\t\twindowsHosts,\n\t\t\twindowsContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"host:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", windowsHosts, windowsContainer, mode),\n\t\t\t\"\",\n\t\t\twindowsHosts,\n\t\t\twindowsContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", name, windowsContainer, mode),\n\t\t\tname,\n\t\t\t\"\",\n\t\t\twindowsContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:host:container\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", name, windowsHosts, windowsContainer),\n\t\t\tname,\n\t\t\twindowsHosts,\n\t\t\twindowsContainer,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"host:container\",\n\t\t\tfmt.Sprintf(\"%s:%s\", windowsHosts, windowsContainer),\n\t\t\t\"\",\n\t\t\twindowsHosts,\n\t\t\twindowsContainer,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s\", windowsContainer, mode),\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\twindowsContainer,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:container\",\n\t\t\tfmt.Sprintf(\"%s:%s\", name, windowsContainer),\n\t\t\tname,\n\t\t\t\"\",\n\t\t\twindowsContainer,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"container\",\n\t\t\twindowsContainer,\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\twindowsContainer,\n\t\t\t\"\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tname, host, container, mode, err := ParseVolume(test.volume)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"In test case %q, returned unexpected error %v\", test.test, err)\n\t\t}\n\t\tif name != test.name {\n\t\t\tt.Errorf(\"In test case %q, returned volume name %s, expected %s\", test.test, name, test.name)\n\t\t}\n\t\tif host != test.host {\n\t\t\tt.Errorf(\"In test case %q, returned host path %s, expected %s\", test.test, host, test.host)\n\t\t}\n\t\tif container != test.container {\n\t\t\tt.Errorf(\"In test case %q, returned container path %s, expected %s\", test.test, container, test.container)\n\t\t}\n\t\tif mode != test.mode {\n\t\t\tt.Errorf(\"In test case %q, returned access mode %s, expected %s\", test.test, mode, test.mode)\n\t\t}\n\t}\n}\n\nfunc TestParseVolume(t *testing.T) {\n\tname1 := \"datavolume\"\n\thost1 := \"./cache\"\n\thost2 := \"~/configs\"\n\tcontainer1 := \"/tmp/cache\"\n\tcontainer2 := \"/etc/configs/\"\n\tmode := \"rw\"\n\n\ttests := []struct {\n\t\ttest, volume, name, host, container, mode string\n\t}{\n\t\t{\n\t\t\t\"name:host:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s:%s\", name1, host1, container1, mode),\n\t\t\tname1,\n\t\t\thost1,\n\t\t\tcontainer1,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"host:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", host2, container2, mode),\n\t\t\t\"\",\n\t\t\thost2,\n\t\t\tcontainer2,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", name1, container1, mode),\n\t\t\tname1,\n\t\t\t\"\",\n\t\t\tcontainer1,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:host:container\",\n\t\t\tfmt.Sprintf(\"%s:%s:%s\", name1, host1, container1),\n\t\t\tname1,\n\t\t\thost1,\n\t\t\tcontainer1,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"host:container\",\n\t\t\tfmt.Sprintf(\"%s:%s\", host1, container1),\n\t\t\t\"\",\n\t\t\thost1,\n\t\t\tcontainer1,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"container:mode\",\n\t\t\tfmt.Sprintf(\"%s:%s\", container2, mode),\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\tcontainer2,\n\t\t\tmode,\n\t\t},\n\t\t{\n\t\t\t\"name:container\",\n\t\t\tfmt.Sprintf(\"%s:%s\", name1, container1),\n\t\t\tname1,\n\t\t\t\"\",\n\t\t\tcontainer1,\n\t\t\t\"\",\n\t\t},\n\t\t{\n\t\t\t\"container\",\n\t\t\tcontainer2,\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\tcontainer2,\n\t\t\t\"\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tname, host, container, mode, err := ParseVolume(test.volume)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"In test case %q, returned unexpected error %v\", test.test, err)\n\t\t}\n\t\tif name != test.name {\n\t\t\tt.Errorf(\"In test case %q, returned volume name %s, expected %s\", test.test, name, test.name)\n\t\t}\n\t\tif host != test.host {\n\t\t\tt.Errorf(\"In test case %q, returned host path %s, expected %s\", test.test, host, test.host)\n\t\t}\n\t\tif container != test.container {\n\t\t\tt.Errorf(\"In test case %q, returned container path %s, expected %s\", test.test, container, test.container)\n\t\t}\n\t\tif mode != test.mode {\n\t\t\tt.Errorf(\"In test case %q, returned access mode %s, expected %s\", test.test, mode, test.mode)\n\t\t}\n\t}\n}\n\nfunc TestGetComposeFileDir(t *testing.T) {\n\toutput, err := GetComposeFileDir([]string{\"foobar/docker-compose.yaml\"})\n\tif err != nil {\n\t\tt.Errorf(\"Error with GetComposeFileDir %v\", err)\n\t}\n\tif !strings.Contains(output, \"foobar\") {\n\t\tt.Errorf(\"Expected $PWD/foobar, got %v\", output)\n\t}\n}\n"
  },
  {
    "path": "pkg/utils/archive/tar.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    http://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*/\n\npackage archive\n\nimport (\n\t\"archive/tar\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n/*\nCreateTarball creates a tarball for source and dumps it to target path\n\nFunction modified and added from https://github.com/mholt/archiver/blob/master/tar.go\n*/\nfunc CreateTarball(source, target string) error {\n\ttarfile, err := os.Create(target)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer tarfile.Close()\n\n\ttarball := tar.NewWriter(tarfile)\n\tdefer tarball.Close()\n\n\tinfo, err := os.Stat(source)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tvar baseDir string\n\tif info.IsDir() {\n\t\tbaseDir = filepath.Base(source)\n\t}\n\n\treturn filepath.Walk(source,\n\t\tfunc(path string, info os.FileInfo, err error) error {\n\t\t\tif baseDir == path {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\theader, err := tar.FileInfoHeader(info, info.Name())\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif baseDir != \"\" {\n\t\t\t\tif strings.HasSuffix(source, \"/\") {\n\t\t\t\t\theader.Name = strings.TrimPrefix(path, source)\n\t\t\t\t} else {\n\t\t\t\t\theader.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))\n\t\t\t\t}\n\t\t\t\t//println(\"Header name\", header.Name)\n\t\t\t}\n\n\t\t\tif err := tarball.WriteHeader(header); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif info.IsDir() {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tfile, err := os.Open(path)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer file.Close()\n\t\t\t_, err = io.Copy(tarball, file)\n\t\t\treturn err\n\t\t})\n}\n"
  },
  {
    "path": "pkg/utils/docker/build.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    http://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*/\n\npackage docker\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"strconv\"\n\t\"strings\"\n\n\tdockerlib \"github.com/fsouza/go-dockerclient\"\n\t\"github.com/kubernetes/kompose/pkg/utils/archive\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// Build will provide methods for interaction with API regarding building images\ntype Build struct {\n\tClient dockerlib.Client\n}\n\n/*\nBuildImage builds a Docker image via the Docker API or Docker CLI.\nTakes the source directory and image name and then builds the appropriate image. Tarball is utilized\nin order to make building easier.\n\nif the DOCKER_BUILDKIT is '1', then we will use the docker CLI to build the image\n*/\nfunc (c *Build) BuildImage(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, buildTarget string) error {\n\tlog.Infof(\"Building image '%s' from directory '%s'\", image, path.Base(source))\n\n\toutputBuffer := bytes.NewBuffer(nil)\n\tvar err error\n\n\tif usecli, _ := strconv.ParseBool(os.Getenv(\"DOCKER_BUILDKIT\")); usecli {\n\t\terr = buildDockerCli(source, image, dockerfile, buildargs, outputBuffer, buildTarget)\n\t} else {\n\t\terr = c.buildDockerClient(source, image, dockerfile, buildargs, outputBuffer, buildTarget)\n\t}\n\n\tlog.Debugf(\"Image %s build output:\\n%s\", image, outputBuffer)\n\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Unable to build image. For more output, use -v or --verbose when converting.\")\n\t}\n\n\tlog.Infof(\"Image '%s' from directory '%s' built successfully\", image, path.Base(source))\n\n\treturn nil\n}\n\nfunc (c *Build) buildDockerClient(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, outputBuffer *bytes.Buffer, buildTarget string) error {\n\t// Create a temporary file for tarball image packaging\n\ttmpFile, err := os.CreateTemp(os.TempDir(), \"kompose-image-build-\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tlog.Debugf(\"Created temporary file %v for Docker image tarballing\", tmpFile.Name())\n\n\t// Create a tarball of the source directory in order to build the resulting image\n\terr = archive.CreateTarball(strings.Join([]string{source, \"\"}, \"/\"), tmpFile.Name())\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Unable to create a tarball\")\n\t}\n\n\t// Load the file into memory\n\ttarballSource, err := os.Open(tmpFile.Name())\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Unable to load tarball into memory\")\n\t}\n\n\t// Let's create all the options for the image building.\n\topts := dockerlib.BuildImageOptions{\n\t\tName:         image,\n\t\tInputStream:  tarballSource,\n\t\tOutputStream: outputBuffer,\n\t\tDockerfile:   dockerfile,\n\t\tBuildArgs:    buildargs,\n\t\tTarget:       buildTarget,\n\t}\n\n\t// Build it!\n\treturn c.Client.BuildImage(opts)\n}\n\nfunc buildDockerCli(source string, image string, dockerfile string, buildargs []dockerlib.BuildArg, outputBuffer *bytes.Buffer, buildTarget string) error {\n\targs := []string{\"build\", \"-t\", image}\n\n\tif dockerfile != \"\" {\n\t\targs = append(args, \"-f\", dockerfile)\n\t}\n\n\tfor _, buildarg := range buildargs {\n\t\targs = append(args, \"--build-arg\", fmt.Sprintf(\"%s=%s\", buildarg.Name, buildarg.Value))\n\t}\n\n\targs = append(args, source)\n\tif buildTarget != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--target=%s\", buildTarget))\n\t}\n\n\tcmd := exec.Command(\"docker\", args...)\n\tcmd.Stdout = outputBuffer\n\tcmd.Stderr = outputBuffer\n\n\tlog.Debugf(\"Image %s build calling command %v\", image, cmd)\n\n\treturn cmd.Run()\n}\n"
  },
  {
    "path": "pkg/utils/docker/client.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    http://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*/\n\npackage docker\n\nimport (\n\t\"os\"\n\n\tdocker \"github.com/fsouza/go-dockerclient\"\n)\n\n// Client connects to Docker client on host\nfunc Client() (*docker.Client, error) {\n\tvar (\n\t\terr    error\n\t\tclient *docker.Client\n\t)\n\n\tdockerHost := os.Getenv(\"DOCKER_HOST\")\n\n\tif len(dockerHost) > 0 {\n\t\t// Create client instance from Docker's environment variables:\n\t\t// DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH\n\t\tclient, err = docker.NewClientFromEnv()\n\t} else {\n\t\t// Default unix socket end-point\n\t\tendpoint := \"unix:///var/run/docker.sock\"\n\t\tclient, err = docker.NewClient(endpoint)\n\t}\n\tif err != nil {\n\t\treturn client, err\n\t}\n\n\treturn client, nil\n}\n"
  },
  {
    "path": "pkg/utils/docker/image.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    http://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*/\n\npackage docker\n\nimport (\n\t\"path\"\n\n\tdockerparser \"github.com/novln/docker-parser\"\n)\n\n// Image contains the basic information parsed from full image name\n// see github.com/novln/docker-parser Reference\ntype Image struct {\n\tName       string // the image's name (ie: debian[:8.2])\n\tShortName  string // the image's name (ie: debian)\n\tTag        string // the image's tag (or digest)\n\tRegistry   string // the image's registry. (ie: host[:port])\n\tRepository string // the image's repository. (ie: registry/name)\n\tRemote     string // the image's remote identifier. (ie: registry/name[:tag])\n}\n\n// NewImageFromParsed method returns the docker image from the docker parser reference\nfunc NewImageFromParsed(parsed *dockerparser.Reference) Image {\n\treturn Image{\n\t\tName:       parsed.Name(),\n\t\tShortName:  parsed.ShortName(),\n\t\tTag:        parsed.Tag(),\n\t\tRegistry:   parsed.Registry(),\n\t\tRepository: parsed.Repository(),\n\t\tRemote:     parsed.Remote(),\n\t}\n}\n\n// ParseImage Using https://github.com/novln/docker-parser in order to parse the appropriate name and registry.\n// 1. Return default registry when the registry is not specified from image\n// 2. Return target registry when the registry is specified from command line\nfunc ParseImage(fullImageName string, targetRegistry string) (Image, error) {\n\tvar image Image\n\n\t// First parse to fill default fields for image\n\t// See github.com/novln/docker-parser/docker/reference.go\n\tparsedImage, err := dockerparser.Parse(fullImageName)\n\n\tif err != nil {\n\t\treturn image, err\n\t}\n\n\t// Registry from command argument is high priority than parsed from name of image.\n\tif targetRegistry != \"\" {\n\t\t// Parse again for validating registry\n\t\tfullImageName = path.Join(targetRegistry, parsedImage.Name())\n\t\tparsedImage, err = dockerparser.Parse(fullImageName)\n\t\tif err != nil {\n\t\t\treturn image, err\n\t\t}\n\t}\n\n\timage = NewImageFromParsed(parsedImage)\n\n\treturn image, nil\n}\n"
  },
  {
    "path": "pkg/utils/docker/image_test.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    http://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*/\n\npackage docker\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestParseImage(t *testing.T) {\n\ttype args struct {\n\t\tfullImageName  string\n\t\ttargetRegistry string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    Image\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\t\"Given empty registry Then default registry expected\",\n\t\t\targs{\n\t\t\t\t\"foo/bar\",\n\t\t\t\t\"\",\n\t\t\t},\n\t\t\tImage{\n\t\t\t\t\"foo/bar:latest\",\n\t\t\t\t\"foo/bar\",\n\t\t\t\t\"latest\",\n\t\t\t\t\"docker.io\",\n\t\t\t\t\"docker.io/foo/bar\",\n\t\t\t\t\"docker.io/foo/bar:latest\",\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Given registry from image Then parsed registry expected\",\n\t\t\targs{\n\t\t\t\t\"docker.io/foo/bar\",\n\t\t\t\t\"\",\n\t\t\t},\n\t\t\tImage{\n\t\t\t\t\"foo/bar:latest\",\n\t\t\t\t\"foo/bar\",\n\t\t\t\t\"latest\",\n\t\t\t\t\"docker.io\",\n\t\t\t\t\"docker.io/foo/bar\",\n\t\t\t\t\"docker.io/foo/bar:latest\",\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Given target registry Then target registry expected\",\n\t\t\targs{\n\t\t\t\t\"foo/bar\",\n\t\t\t\t\"localhost:5000\",\n\t\t\t},\n\t\t\tImage{\n\t\t\t\t\"foo/bar:latest\",\n\t\t\t\t\"foo/bar\",\n\t\t\t\t\"latest\",\n\t\t\t\t\"localhost:5000\",\n\t\t\t\t\"localhost:5000/foo/bar\",\n\t\t\t\t\"localhost:5000/foo/bar:latest\",\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Given registry from image and target registry Then target registry expected\",\n\t\t\targs{\n\t\t\t\t\"docker.io/foo/bar\",\n\t\t\t\t\"localhost:5000\",\n\t\t\t},\n\t\t\tImage{\n\t\t\t\t\"foo/bar:latest\",\n\t\t\t\t\"foo/bar\",\n\t\t\t\t\"latest\",\n\t\t\t\t\"localhost:5000\",\n\t\t\t\t\"localhost:5000/foo/bar\",\n\t\t\t\t\"localhost:5000/foo/bar:latest\",\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := ParseImage(tt.args.fullImageName, tt.args.targetRegistry)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"ParseImage() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"ParseImage() got = %+v, want %+v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/utils/docker/push.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    http://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*/\n\npackage docker\n\nimport (\n\t\"bytes\"\n\n\tdockerlib \"github.com/fsouza/go-dockerclient\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// Push will provide methods for interaction with API regarding pushing images\ntype Push struct {\n\tClient dockerlib.Client\n}\n\n/*\nPushImage pushes a Docker image via the Docker API. Takes the image name,\nparses the URL details and then push based on environment authentication\ncredentials.\n*/\nfunc (c *Push) PushImage(image Image) error {\n\tlog.Infof(\"Pushing image '%s' to registry '%s'\", image.Name, image.Registry)\n\n\t// Let's setup the push and authentication options\n\toutputBuffer := bytes.NewBuffer(nil)\n\toptions := dockerlib.PushImageOptions{\n\t\tTag:          image.Tag,\n\t\tName:         image.Repository,\n\t\tRegistry:     image.Registry,\n\t\tOutputStream: outputBuffer,\n\t}\n\n\t// Retrieve the authentication configuration file\n\t// Files checked as per https://godoc.org/github.com/fsouza/go-dockerclient#NewAuthConfigurationsFromFile\n\t// $DOCKER_CONFIG/config.json, $HOME/.docker/config.json , $HOME/.dockercfg\n\tcredentials, err := dockerlib.NewAuthConfigurationsFromDockerCfg()\n\tif err != nil {\n\t\tlog.Warn(errors.Wrap(err, \"Unable to retrieve .docker/config.json authentication details. Check that 'docker login' works successfully on the command line.\"))\n\t} else {\n\t\thandleDockerRegistry(credentials)\n\t}\n\n\t// Find the authentication matched to registry\n\tauth, ok := credentials.Configs[image.Registry]\n\tif !ok {\n\t\t// Fallback to unauthenticated access in case if no auth credentials are retrieved\n\t\tlog.Infof(\"Authentication credential of registry '%s' is not found. Will try push without authentication.\", image.Registry)\n\t\t// Header X-Registry-Auth is required\n\t\t// Or API error (400): Bad parameters and missing X-Registry-Auth: EOF will throw\n\t\t// Just to make not empty struct\n\t\tauth = dockerlib.AuthConfiguration{Username: \"docker\"}\n\t}\n\n\tlog.Debugf(\"Pushing image with options %+v\", options)\n\terr = c.Client.PushImage(options, auth)\n\tif err != nil {\n\t\tlog.Errorf(\"Unable to push image '%s' to registry '%s'. Error: %s\", image.Name, image.Registry, err)\n\t\treturn errors.New(\"unable to push docker image(s). Check that `docker login` works successfully on the command line\")\n\t}\n\n\tlog.Debugf(\"Image '%+v' push output:\\n%s\", image, outputBuffer)\n\tlog.Infof(\"Successfully pushed image '%s' to registry '%s'\", image.Name, image.Registry)\n\treturn nil\n}\n\n// handleDockerRegistry adapt legacy docker registry address\n// After docker login to docker.io, there must be https://index.docker.io/v1/ in config.json of authentication\n// Reference: https://docs.docker.com/engine/api/v1.23/\n//\n//\t> However (for legacy reasons) the “official” Docker, Inc. hosted registry\n//\t> must be specified with both a “https://” prefix and a “/v1/” suffix\n//\t> even though Docker will prefer to use the v2 registry API.\nfunc handleDockerRegistry(auth *dockerlib.AuthConfigurations) {\n\tconst address = \"docker.io\"\n\tconst legacyAddress = \"https://index.docker.io/v1/\"\n\n\tif legacyAddressConfig, ok := auth.Configs[legacyAddress]; ok {\n\t\tauth.Configs[address] = legacyAddressConfig\n\t}\n}\n"
  },
  {
    "path": "pkg/utils/docker/tag.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    http://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*/\n\npackage docker\n\nimport (\n\tdockerlib \"github.com/fsouza/go-dockerclient\"\n\t\"github.com/pkg/errors\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// Tag will provide methods for interaction with API regarding tagging images\ntype Tag struct {\n\tClient dockerlib.Client\n}\n\n// TagImage function is responsible for tagging the docker image\nfunc (c *Tag) TagImage(image Image) error {\n\toptions := dockerlib.TagImageOptions{\n\t\tTag:  image.Tag,\n\t\tRepo: image.Repository,\n\t}\n\n\tlog.Infof(\"Tagging image '%s' into repository '%s'\", image.Name, image.Repository)\n\terr := c.Client.TagImage(image.ShortName, options)\n\tif err != nil {\n\t\tlog.Errorf(\"Unable to tag image '%s' into repository '%s'. Error: %s\", image.Name, image.Registry, err)\n\t\treturn errors.New(\"unable to tag docker image(s)\")\n\t}\n\n\tlog.Infof(\"Successfully tagged image '%s'\", image.Remote)\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/version/version.go",
    "content": "package version\n\nvar (\n\t// VERSION  is version number that will be displayed when running ./kompose version\n\tVERSION = \"1.38.0\"\n\t// GITCOMMIT is hash of the commit that will be displayed when running ./kompose version\n\t// this will be overwritten when running  build like this: go build -ldflags=\"-X github.com/kubernetes/kompose/pkg/version.GITCOMMIT=$(GITCOMMIT)\"\n\t// HEAD is default indicating that this was not set during build\n\tGITCOMMIT = \"HEAD\"\n)\n"
  },
  {
    "path": "script/check-gofmt.sh",
    "content": "#!/bin/bash\n\n# Copyright 2017 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.\n\n\n# This checks if all go source files in current directory are format using gofmt\n\n# Ignore vendor directory that's NOT in the main path\nGO_FILES=$(find . -path ./vendor -prune -o -name '*.go' -print )\n\nfor file in $GO_FILES; do\n\tgofmtOutput=$(gofmt -l \"$file\")\n\tif [ \"$gofmtOutput\" ]; then\n\t\terrors+=(\"$gofmtOutput\")\n\tfi\ndone \n\n\nif [ ${#errors[@]} -eq 0 ]; then\n\techo \"gofmt OK\"\nelse\n\techo \"gofmt ERROR - These files are not formatted by gofmt:\"\n\tfor err in \"${errors[@]}\"; do\n\t\techo \"$err\"\n\tdone\n\texit 1\nfi"
  },
  {
    "path": "script/manual-docs-sync.sh",
    "content": "#!/usr/bin/env bash\n\n## README:\n## This script is ran by running:\n## cd script\n## ./manual-docs-sync.sh\n##\n## This will take all documentation from the /docs folder of the main dir and push to the gh-pages branch (granted you have access)\n\nDOCS_REPO_NAME=\"kompose\"\nDOCS_REPO_URL=\"git@github.com:kubernetes/kompose.git\"\nDOCS_BRANCH=\"gh-pages\"\nDOCS_FOLDER=\"docs\"\n\n# clone the repo\ngit clone \"$DOCS_REPO_URL\" \"$DOCS_REPO_NAME\"\n\n# change to that directory (to prevent accidental pushing to main, etc.)\ncd \"$DOCS_REPO_NAME\"\n\n# switch to gh-pages and grab the docs folder from main\ngit checkout gh-pages\ngit checkout main -- docs\n\n# Copy it all over to the current directory\ncp -r docs/* .\nrm -r docs\n\ngit add --all\n\n# Check if anything changed, and if it's the case, push to origin/main.\nif git commit -m 'Update docs' -m \"Synchronize documentation against website\" ; then\n  git push\nfi\n\n# cd back to the original root folder\ncd ..\n"
  },
  {
    "path": "script/release.sh",
    "content": "#!/usr/bin/env bash\n\n# Copyright 2017 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.\n\n# Constants. Enter relevant repo information here.\nUPSTREAM_REPO=\"kubernetes\"\nCLI=\"kompose\"\n\nusage() {\n  echo \"This will prepare $CLI for release!\"\n  echo \"\"\n  echo \"Requirements:\"\n  echo \" git\"\n  echo \" gh\"\n  echo \" \"\n  echo \"Not only that, but you must have permission for:\"\n  echo \" Tagging releases within Github\"\n  echo \"\"\n}\n\nrequirements() {\n\n  if ! hash git 2>/dev/null; then\n    echo \"ERROR: No git.\"\n    exit 0\n  fi\n\n}\n\n# Make sure that upstream had been added to the repo \ninit_sync() {\n  CURRENT_ORIGIN=`git config --get remote.origin.url`\n  CURRENT_UPSTREAM=`git config --get remote.upstream.url`\n  ORIGIN=\"git@github.com:$ORIGIN_REPO/$CLI.git\"\n  UPSTREAM=\"git@github.com:$UPSTREAM_REPO/$CLI.git\"\n\n  if [ $CURRENT_ORIGIN != $ORIGIN ]; then\n    echo \"Origin repo must be set to $ORIGIN\"\n    exit 0\n  fi\n\n  if [ $CURRENT_UPSTREAM != $UPSTREAM ]; then\n    echo \"Upstream repo must be set to $UPSTREAM\"\n    exit 0\n  fi\n\n  git checkout main\n  git fetch upstream\n  git merge upstream/main\n  git checkout -b release-$1\n}\n\nreplaceversion() {\n  echo \"Replaced version in pkg/version/version.go\"\n  sed -i \"s/$1/$2/g\" pkg/version/version.go || gsed -i \"s/$1/$2/g\" pkg/version/version.go\n\n  echo \"Replaced version in README.md\"\n  sed -i \"s/$1/$2/g\" README.md || gsed -i \"s/$1/$2/g\" README.md\n\n  echo \"Replaced version in docs/installation.md\"\n  sed -i \"s/$1/$2/g\" docs/installation.md || gsed -i \"s/$1/$2/g\" docs/installation.md\n  sed -i \"s/$1/$2/g\" site/docs/installation.md || gsed -i \"s/$1/$2/g\" site/docs/installation.md\n\n  echo \"Replaced version in build/VERSION\"\n  sed -i \"s/$1/$2/g\" build/VERSION || gsed -i \"s/$1/$2/g\" build/VERSION\n\n\n  echo \"Ignore above errors if you're using macOS\"\n}\n\nbuild_binaries() {\n  make cross\n}\n\ncreate_tarballs() {\n  # cd into the bin directory so we don't have '/bin' inside the tarball\n  cd bin\n  for f in *\n  do\n    tar cvzf $f.tar.gz $f\n  done\n  cd ..\n}\n\ngit_commit() {\n  BRANCH=`git symbolic-ref --short HEAD`\n  if [ -z \"$BRANCH\" ]; then\n    echo \"Unable to get branch name, is this even a git repo?\"\n    return 1\n  fi\n  echo \"Branch: \" $BRANCH\n\n  git add .\n  git commit -m \"$1 Release\"\n  git push origin $BRANCH\n  gh pr create\n\n  echo \"\"\n  echo \"PR opened against main to update version\"\n  echo \"MERGE THIS BEFORE CONTINUING\"\n  echo \"\"\n}\n\ngit_pull() {\n  git pull\n}\n\n\ngit_sync() {\n  git fetch upstream main\n  git rebase upstream/main\n}\n\ngenerate_install_guide() {\n  echo \"\n# Installation\n\n__Linux and macOS:__\n\n\\`\\`\\`sh\n# Linux\ncurl -L https://github.com/kubernetes/kompose/releases/download/v$1/kompose-linux-amd64 -o kompose\n\n# Linux ARM64\ncurl -L https://github.com/kubernetes/kompose/releases/download/v$1/kompose-linux-arm64 -o kompose\n\n# macOS\ncurl -L https://github.com/kubernetes/kompose/releases/download/v$1/kompose-darwin-amd64 -o kompose\n\n# macOS ARM64\ncurl -L https://github.com/kubernetes/kompose/releases/download/v$1/kompose-darwin-arm64 -o kompose\n\nchmod +x kompose\nsudo mv ./kompose /usr/local/bin/kompose\n\\`\\`\\`\n\n__Windows:__\n\nDownload from [GitHub](https://github.com/kubernetes/kompose/releases/download/v$1/kompose-windows-amd64.exe) and add the binary to your PATH.\n\n__Checksums:__\n\n| Filename        | SHA256 Hash |\n| ------------- |:-------------:|\" > install_guide.txt\n\n  touch bin/SHA256_SUM\n\n  for f in bin/*\n  do\n    HASH=`sha256sum $f | head -n1 | awk '{print $1;}'`\n    NAME=`echo $f | sed \"s,bin/,,g\"`\n    echo \"[$NAME](https://github.com/kubernetes/kompose/releases/download/v$1/$NAME) | $HASH\" >> install_guide.txt\n    echo \"$HASH $NAME\" >> bin/SHA256_SUM\n  done\n\n}\n\npush() {\n\n  echo \"!!PLEASE READ!!\n  1. Say YES to GitHub generating the release notes\n  2. Append install_guide.txt to the TOP of the release notes when prompted\n  3. Double check that the binaries have been UPLOADED!\n  \"\n\n  gh release create v$1 bin/*\n\n  echo \"DONE\"\n  echo \"DOUBLE CHECK IT:\"\n  echo \"!!!\"\n  echo \"https://github.com/$UPSTREAM_REPO/$CLI/releases/edit/$1\"\n  echo \"!!!\"\n}\n\nclean() {\n  rm install_guide.txt\n  rm -r bin/*\n}\n\nmain() {\n  local cmd=$1\n  usage\n\n  requirements\n\n  echo \"What is your Github username? (location of your $CLI fork)\"\n  read ORIGIN_REPO \n  echo \"You entered: $ORIGIN_REPO\"\n  echo \"\"\n  \n  echo \"\"\n  echo \"First, please enter the version of the NEW release: \"\n  read VERSION\n  echo \"You entered: $VERSION\"\n  echo \"\"\n\n  echo \"\"\n  echo \"Second, please enter the version of the LAST release: \"\n  read PREV_VERSION\n  echo \"You entered: $PREV_VERSION\"\n  echo \"\"\n\n  clear\n\n  echo \"Now! It's time to go through each step of releasing $CLI!\"\n  echo \"If one of these steps fails / does not work, simply re-run ./release.sh\"\n  echo \"Re-enter the information at the beginning and continue on the failed step\"\n  echo \"\"\n\n  PS3='Please enter your choice: '\n  options=(\n  \"Initial sync with upstream\"\n  \"Replace version number\"\n  \"Create PR\"\n  \"Sync with upstream\"\n  \"Build binaries\"\n  \"Create tarballs\"\n  \"Generate install guide\"\n  \"Upload the binaries and push to GitHub release page\"\n  \"Update the website\"\n  \"Clean\"\n  \"Quit\")\n  select opt in \"${options[@]}\"\n  do\n      echo \"\"\n      case $opt in\n          \"Initial sync with upstream\")\n              init_sync $VERSION\n              ;;\n          \"Replace version number\")\n              replaceversion $PREV_VERSION $VERSION\n              ;;\n          \"Create PR\")\n              git_commit $VERSION\n              ;;\n          \"Sync with upstream\")\n              git_sync\n              ;;\n          \"Build binaries\")\n              build_binaries\n              ;;\n          \"Create tarballs\")\n              create_tarballs\n              ;;\n          \"Generate install guide\")\n              generate_install_guide $VERSION\n              ;;\n          \"Upload the binaries and push to GitHub release page\")\n              push $VERSION\n              ;;\n          \"Update the website\")\n              echo \"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\"\n              echo \"Run ./script/manual-docs-sync.sh on the main branch\"\n              echo \"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\"\n              ;;\n          \"Clean\")\n              clean $VERSION\n              ;;\n          \"Quit\")\n              clear\n              break\n              ;;\n          *) echo invalid option;;\n      esac\n      echo \"\"\n  done\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "script/test/README.md",
    "content": "# Functional Test\n\n### Requirements\n\nInstall `jq - commandline JSON processor` with minimum version of 1.5\n\n\n### Running tests\n\nTest running ./cmd/tests.sh\n\n\n"
  },
  {
    "path": "script/test/cmd/cmd_test.go",
    "content": "package cmd\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"testing\"\n)\n\nvar ProjectPath = \"$GOPATH/src/github.com/kubernetes/kompose/\"\nvar BinaryLocation = os.ExpandEnv(ProjectPath + \"kompose\")\n\nfunc Test_stdin(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping test in short mode.\")\n\t}\n\tkjson := `{\"version\": \"2\",\"services\": {\"redis\": {\"image\": \"redis:3.0\",\"ports\": [\"6379\"]}}}`\n\tcmdStr := fmt.Sprintf(\"%s convert --stdout -j -f - <<EOF\\n%s\\nEOF\\n\", BinaryLocation, kjson)\n\tsubproc := exec.Command(\"/bin/sh\", \"-c\", cmdStr)\n\toutput, err := subproc.Output()\n\tif err != nil {\n\t\tfmt.Println(\"error\", err)\n\t}\n\tg, err := os.ReadFile(\"/tmp/output-k8s.json\")\n\tif !bytes.Equal(output, g) {\n\t\tt.Errorf(\"Test Failed\")\n\t}\n}\n"
  },
  {
    "path": "script/test/cmd/fix_detached_head.sh",
    "content": "#!/usr/bin/env bash\n\n# Copyright 2017 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.\n\n# Reference Link: https://github.com/theochem/horton/blob/master/tools/qa/fix_detached_head.sh\n\n# Only do something if the HEAD is detached.\nif [ $(git rev-parse --abbrev-ref HEAD) == 'HEAD' ]; then\n    # Give the  some random name that no serious person would use.\n    git checkout -b build_branch\nfi\n"
  },
  {
    "path": "script/test/cmd/globals.sh",
    "content": "#!/bin/bash\n\n# Copyright 2017 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.\n\nTEMP_DIR=\"/tmp/kompose\"\nTEMP_STDOUT=$TEMP_DIR/test-stdout\nTEMP_STDERR=$TEMP_DIR/test-stderr\nEXIT_STATUS=0\n"
  },
  {
    "path": "script/test/cmd/lib.sh",
    "content": "#!/bin/bash\n\n# Copyright 2017 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.\n\nif type \"greadlink\" > /dev/null; then\n  KOMPOSE_ROOT=$(greadlink -f $(dirname \"${BASH_SOURCE}\")/../../..)\nelse\n  KOMPOSE_ROOT=$(readlink -f $(dirname \"${BASH_SOURCE}\")/../../..)\nfi\n\nstat=\"stat\"\nif type \"gstat\" > /dev/null; then\n  stat=\"gstat\"\nfi\n\nsource $KOMPOSE_ROOT/script/test/cmd/globals.sh\n\n# setup all the things needed to run tests\nfunction convert::init() {\n    mkdir -p $TEMP_DIR\n    SUCCESS_MSGS=\"\"\n    FAIL_MSGS=\"\"\n}\nreadonly -f convert::init\n\n# remove all the temporary files created for test\nfunction convert::teardown() {\n    rm -rf $TEMP_DIR\n    SUCCESS_MSGS=\"\"\n    FAIL_MSGS=\"\"\n}\nreadonly -f convert::teardown\n\n# print about test start information\nfunction convert::start_test() {\n    convert::init\n    echo -e \"\\n\\n===> Starting test <===\"\n    echo $@\n}\nreadonly -f convert::start_test\n\n# print in green about the test being passed\nfunction convert::print_pass() {\n    tput setaf 2\n    tput bold\n    echo -en \"PASS: $@\"\n    tput sgr0\n}\nreadonly -f convert::print_pass\n\n# print in red about the test failed\nfunction convert::print_fail() {\n    tput setaf 1\n    tput bold\n    echo -en \"FAIL: $@\"\n    tput sgr0\n\n}\nreadonly -f convert::print_fail\n\n# run a cmd, which saves stdout output to TEMP_STDOUT\n# and saves errors to TEMP_STDERR files and returns exit status\nfunction convert::run_cmd() {\n    cmd=$@\n\n    $cmd 2>$TEMP_STDERR >$TEMP_STDOUT\n    return $?\n}\nreadonly -f convert::run_cmd\n\n\nfunction convert::expect_cmd_success() {\n    local cmd=$1\n\n    convert::start_test \"convert::expect_cmd_success: Running: '${cmd}'\"\n\n    convert::run_cmd $cmd\n    exit_status=$?\n    if [ $exit_status -ne 0 ]; then FAIL_MSGS=$FAIL_MSGS\"exit status: $exit_status\\n\"; return $exit_status; fi\n}\n# run the command and match the output to the existing file\n# if error then save error string in FAIL_MSGS\n# if success save pass string in SUCCESS_MSGS\nfunction convert::match_output() {\n    local cmd=$1\n    local expected_output=$2\n\n    convert::run_cmd $cmd\n    exit_status=$?\n    if [ $exit_status -ne 0 ]; then FAIL_MSGS=$FAIL_MSGS\"exit status: $exit_status\\n\"; return $exit_status; fi\n\n    match=$(dyff between --ignore-order-changes --set-exit-code $expected_output $TEMP_STDOUT)\n    if [ $? -eq 0 ]; then SUCCESS_MSGS=$SUCCESS_MSGS\"converted output matches\\n\"; return 0;\n    else FAIL_MSGS=$FAIL_MSGS\"converted output does not match\\n\"; echo $match; return 1; \n    fi\n}\nreadonly -f convert::match_output\n\n# function called from outside which accepts cmd to run and\n# file to compare output with\nfunction convert::expect_success() {\n    local cmd=$1\n    local expected_output=$2\n\n    convert::start_test \"convert::expect_success: Running: '${cmd}' expected_output: '${expected_output}'\"\n\n    convert::match_output \"$cmd\" \"$expected_output\"\n    if [ $? -ne 0 ]; then convert::print_fail $FAIL_MSGS; convert::teardown; EXIT_STATUS=1; return 1;\n    else convert::print_pass $SUCCESS_MSGS; fi\n\n    # check if no warnings are generated? If yes then fail\n    warnings=$($stat -c%s $TEMP_STDERR)\n    if [ $warnings -ne 0 ]; then convert::print_fail \"warnings given: $(cat $TEMP_STDERR)\"; EXIT_STATUS=1; fi\n\n    convert::teardown\n}\nreadonly -f convert::expect_success\n\n# function called from outside, which accepts cmd to run,\n# expected output file and warnings if any\nfunction convert::expect_success_and_warning() {\n    local cmd=$1\n    local expected_output=$2\n    local expected_warning=$3\n\n    convert::start_test \"convert::expect_success_and_warning: Running: '${cmd}' expected_output: '${expected_output}' expected_warning: '${expected_warning}'\"\n\n    convert::match_output \"$cmd\" \"$expected_output\"\n    if [ $? -ne 0 ]; then convert::print_fail $FAIL_MSGS; convert::teardown; EXIT_STATUS=1; return 1;\n    else convert::print_pass $SUCCESS_MSGS; fi\n\n    grep -i \"$expected_warning\" $TEMP_STDERR > /dev/null\n    local exit_status=$?\n    if [ $exit_status -ne 0 ]; then convert::print_fail \"no warning found: '$expected_warning'\"; EXIT_STATUS=1;\n    else convert::print_pass \"warning found: '$expected_warning'\"; fi\n\n    convert::teardown\n    return $exit_status\n}\nreadonly -f convert::expect_success_and_warning\n\n# function called from outside, which accepts cmd to run,\n# expects warning, without caring if the cmd ran passed or failed\nfunction convert::expect_warning() {\n    local cmd=$1\n    local expected_warning=$2\n\n    convert::start_test \"convert::expect_warning: Running: '${cmd}' expected_warning: '${expected_warning}'\"\n\n    $cmd 2>$TEMP_STDERR >$TEMP_STDOUT\n\n    grep -i \"$expected_warning\" $TEMP_STDERR > /dev/null\n    local exit_status=$?\n    if [ $exit_status -ne 0 ]; then convert::print_fail \"no warning found: '$expected_warning'\"; EXIT_STATUS=1;\n    else convert::print_pass \"warning found: '$expected_warning'\"; fi\n\n    convert::teardown\n    return $exit_status\n}\nreadonly -f convert::expect_warning\n\n# function called from outside, which accepts cmd to run,\n# expects failure, if the command passes then errors out.\nfunction convert::expect_failure() {\n    local cmd=$1\n\n    convert::start_test \"convert::expect_failure: Running: '${cmd}'\"\n    convert::run_cmd $cmd\n    exit_status=$?\n    if [ $exit_status -eq 0 ]; then convert::print_fail \"no error output, returned exit status 0\"; EXIT_STATUS=1;\n    else convert::print_pass \"errored out with exit status: $exit_status\"; fi\n\n    convert::teardown\n    return $exit_status\n}\nreadonly -f convert::expect_failure\n\n# see if the given files exists\nfunction utils::file_exists() {\n    for file in \"$@\"\n    do\n        exit_status=$([ -f $file ]; echo $?)\n        if [ $exit_status -ne 0 ]; then convert::print_fail \"$file does not exist\\n\"; EXIT_STATUS=1;\n        else convert::print_pass \"$file exists\\n\"; fi\n    done\n}\nreadonly -f utils::file_exists\n\n# delete given files one by one\nfunction utils::remove_files() {\n    for file in \"$@\"\n    do\n        rm $file\n    done\n}\nreadonly -f utils::remove_files\n\nfunction convert::check_artifacts_generated() {\n    local cmd=$1\n\n    convert::start_test \"convert::check_artifacts_generated: Running: '${cmd}'\"\n    convert::run_cmd $cmd\n    # passing all args except the first one\n    utils::file_exists \"${@:2}\"\n    utils::remove_files \"${@:2}\"\n\n    convert::teardown\n    return $exit_status\n}\nreadonly -f convert::check_artifacts_generated\n"
  },
  {
    "path": "script/test/cmd/tests.sh",
    "content": "#!/bin/bash\n\n# Copyright 2017 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 pe#rmissions and\n# limitations under the License.\n\n# for mac\nif type \"greadlink\" > /dev/null; then\n  KOMPOSE_ROOT=$(greadlink -f $(dirname \"${BASH_SOURCE}\")/../../..)\nelse\n  KOMPOSE_ROOT=$(readlink -f $(dirname \"${BASH_SOURCE}\")/../../..)\nfi\n\n# for mac (GNU realpath)\nrealpath_cmd=\"realpath\"\nif type \"grealpath\" > /dev/null 2>&1; then\n  realpath_cmd=\"grealpath\"\nfi\n\n# Check for container runtime (docker or podman)\n# These are needed for --build local tests\nCONTAINER_RUNTIME=\"\"\nBUILD_CMD_FLAGS=\"\"\nif docker info > /dev/null 2>&1; then\n  CONTAINER_RUNTIME=\"docker\"\nelif podman info > /dev/null 2>&1; then\n  CONTAINER_RUNTIME=\"podman\"\n  BUILD_CMD_FLAGS=\"--build-command 'podman build' --push-command 'podman push'\"\nfi\n\nsource $KOMPOSE_ROOT/script/test/cmd/lib.sh\n\n# Get current branch and remote url of git repository\nbranch=$(git branch | grep \\* | cut -d ' ' -f2-)\n\nuri=$(git config --get remote.origin.url)\nif [[ $uri != *\".git\"* ]]; then\n    uri=\"${uri}.git\"\nfi\n\n# Get version\nversion=`kompose version`\n\n# Warning Template\nwarning=\"Buildconfig using $uri::$branch as source.\"\n# Replacing variables with current branch and uri\nsed -e \"s;%VERSION%;$version;g\" -e \"s;%URI%;$uri;g\" -e \"s;%REF%;$branch;g\" $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/output-os-template.json > /tmp/output-os.json\n\n\n\n# ## TEST V2\nDIR=\"v2\"\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/$DIR/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/$DIR/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/$DIR/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/$DIR/output-os.yaml\"\n\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\"\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\"\n\n\n\n## TEST V3\nDIR=\"v3.0\"\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/$DIR/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/$DIR/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/$DIR/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/$DIR/output-os.yaml\"\n\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\"\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\"\n\n######\n# Test the output file behavior of kompose convert\n# Default behavior without -o\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/redis-example/compose.yaml convert -j\" \"redis-deployment.json\" \"redis-service.json\" \"web-deployment.json\" \"web-service.json\"\n# Behavior with -o <filename>\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/redis-example/compose.yaml convert -o output_file -j\" \"output_file\"\n# Behavior with -o <dirname>\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/redis-example/compose.yaml convert -o $TEMP_DIR -j\" \"$TEMP_DIR/redis-deployment.json\" \"$TEMP_DIR/redis-service.json\" \"$TEMP_DIR/web-deployment.json\" \"$TEMP_DIR/web-service.json\"\n# Behavior with -o <dirname>/<filename>\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/redis-example/compose.yaml convert -o $TEMP_DIR/output_file -j\" \"$TEMP_DIR/output_file\"\n# Behavior with -o <non-existent-dirname>/\ndst=$TEMP_DIR/output_dir/\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/redis-example/compose.yaml convert -o $dst -j\" \"${dst}redis-deployment.json\" \"${dst}redis-service.json\" \"${dst}web-deployment.json\" \"${dst}web-service.json\"\n# Behavior with -o <non-existent-dirname>/<filename>\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/redis-example/compose.yaml convert -o $TEMP_DIR/output_dir2/output_file -j\" \"$TEMP_DIR/output_dir2/output_file\"\n\n#TEST the pvc-request-size command parameter\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/pvc-request-size/compose.yaml convert -o $TEMP_DIR/output_dir2/output-k8s.json -j --pvc-request-size=300Mi\" \"$TEMP_DIR/output_dir2/output-k8s.json\"\nconvert::check_artifacts_generated \"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/pvc-request-size/compose.yaml convert -o $TEMP_DIR/output_dir2/output-os.json -j --pvc-request-size=300Mi\" \"$TEMP_DIR/output_dir2/output-os.json\"\n\n\n\n\n\n######\n# Test the path of build image (requires docker or podman)\nif [ -n \"$CONTAINER_RUNTIME\" ]; then\n  echo \"Container runtime detected: $CONTAINER_RUNTIME - running build tests\"\n  # Test build v2 absolute compose file\n  convert::check_artifacts_generated \"kompose --build local $BUILD_CMD_FLAGS -f $KOMPOSE_ROOT/script/test/fixtures/buildconfig/compose.yaml convert -o $TEMP_DIR/output_file\" \"$TEMP_DIR/output_file\"\n  # Test build v2 relative compose file\n  relative_path=$($realpath_cmd --relative-to=\"$PWD\" \"$KOMPOSE_ROOT/script/test/fixtures/buildconfig/compose.yaml\")\n  convert::check_artifacts_generated \"kompose --build local $BUILD_CMD_FLAGS -f $relative_path convert -o $TEMP_DIR/output_file\" \"$TEMP_DIR/output_file\"\n  # Test build v3 absolute compose file with context\n  convert::check_artifacts_generated \"kompose --build local $BUILD_CMD_FLAGS -f $KOMPOSE_ROOT/script/test/fixtures/buildconfig/compose-v3.yaml convert -o $TEMP_DIR/output_file\" \"$TEMP_DIR/output_file\"\n  # Test build v3 relative compose file with context\n  relative_path=$($realpath_cmd --relative-to=\"$PWD\" \"$KOMPOSE_ROOT/script/test/fixtures/buildconfig/compose-v3.yaml\")\n  convert::check_artifacts_generated \"kompose --build local $BUILD_CMD_FLAGS -f $relative_path convert -o $TEMP_DIR/output_file\" \"$TEMP_DIR/output_file\"\n\n  # #####\n  # Test the build config with push image\n  # see tests_push_image.sh for local push test\n  # Should warn when push image disabled\n  cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/buildconfig/compose-build-no-image.yaml -o $TEMP_DIR/output_file convert --build=local $BUILD_CMD_FLAGS --push-image-registry=whatever\"\n  convert::expect_warning \"$cmd\" \"Push image registry 'whatever' is specified but push image is disabled, skipping pushing to repository\"\nelse\n  echo \"SKIP: Build tests require docker or podman (neither is running)\"\nfi\n\n#TEST the kompose.volume.storage-class-name label\nconvert::check_artifacts_generated \"kompose -f $KOMPOSE_ROOT/script/test/fixtures/storage-class-name/compose.yaml convert -o $TEMP_DIR/output-k8s.yaml\" \"$TEMP_DIR/output-k8s.yaml\"\nconvert::check_artifacts_generated \"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/storage-class-name/compose.yaml convert -o $TEMP_DIR/output-os.yaml -j\" \"$TEMP_DIR/output-os.yaml\"\n\n# TEST the windows volume\n# windows host path to windows container\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# # TEST the placement\n# should convert placement to affinity\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/deploy/placement/compose-placement.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/deploy/placement/compose-placement.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/deploy/placement/output-placement-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/deploy/placement/output-placement-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n\n# test configmap volume\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/compose.yaml convert --stdout --with-kompose-annotation=false --volumes=configMap\"\nos_cmd=\"kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/compose.yaml convert --stdout --with-kompose-annotation=false --volumes=configMap\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# test configmap volume using service label\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/compose-withlabel.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/compose-withlabel.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-k8s-withlabel.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-os-withlabel.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# test configmap pod generation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-pod/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-pod/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-pod/output-os.yaml\"\nos_cmd=\"kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/configmap-pod/compose.yaml convert --stdout --with-kompose-annotation=false\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test that emptyDir works\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/compose.yaml convert --with-kompose-annotation=false --stdout --volumes emptyDir\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-k8s-empty-vols-template.yaml\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/compose.yaml convert --with-kompose-annotation=false --stdout --volumes emptyDir\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-os-empty-vols-template.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test that emptyvols works\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/compose.yaml convert --with-kompose-annotation=false --stdout --emptyvols\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-k8s.yaml\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/compose.yaml convert --with-kompose-annotation=false --stdout --emptyvols\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# test service expose\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose/compose.yaml convert --stdout --with-kompose-annotation=false\"\nocp_cmd=\"kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/expose/output-k8s.yaml\"\nocp_output=\"$KOMPOSE_ROOT/script/test/fixtures/expose/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$ocp_cmd\" \"$ocp_output\" || exit 1\n\n\n# test service group by volume, not support openshift for now\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/service-group/compose.yaml convert --stdout --with-kompose-annotation=false --service-group-mode=volume --service-group-name=librenms-dispatcher\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/service-group/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# test merge multiple compose files\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/first.yaml -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/second.yaml convert --stdout --with-kompose-annotation=false\"\nocp_cmd=\"kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/first.yaml -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/second.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/multiple-files/output-k8s.yaml\"\nocp_output=\"$KOMPOSE_ROOT/script/test/fixtures/multiple-files/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$ocp_cmd\" \"$ocp_output\" || exit 1\n\n# test health check\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/healthcheck/compose-healthcheck.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/healthcheck/compose-healthcheck.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/healthcheck/output-healthcheck-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/healthcheck/output-healthcheck-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# test statefulset\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/statefulset/compose.yaml convert --stdout --with-kompose-annotation=false --controller statefulset\"\nocp_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/statefulset/compose.yaml convert --stdout --with-kompose-annotation=false --controller statefulset\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/statefulset/output-k8s.yaml\"\nocp_output=\"$KOMPOSE_ROOT/script/test/fixtures/statefulset/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$ocp_cmd\" \"$ocp_output\" || exit 1\n\n# test cronjob\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/cronjob/compose.yaml convert --stdout --with-kompose-annotation=false\"\nocp_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/cronjob/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/cronjob/output-k8s.yaml\"\nocp_output=\"$KOMPOSE_ROOT/script/test/fixtures/cronjob/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$ocp_cmd\" \"$ocp_output\" || exit 1\n\n# test specifying volume type using service label\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose  --provider=openshift -f  $KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/compose.yaml  convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test environment variables interpolation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose  --provider=openshift -f  $KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/compose.yaml  convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test load .env file by default\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/env-dotenv/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose  --provider=openshift -f  $KOMPOSE_ROOT/script/test/fixtures/env-dotenv/compose.yaml  convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/env-dotenv/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/env-dotenv/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test single file output feature\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/single-file-output/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/single-file-output/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test host port and protocol feature\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test external traffic policy feature with valid configuration, warning is coming from the network policy.\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/compose-v1.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-k8s-v1.yaml\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/compose-v1.yaml convert --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-os-v1.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test external traffic policy feature with warning, because we have nodeport with external traffic policy\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/compose-v2.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-k8s-v2.yaml\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/compose-v2.yaml convert --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-os-v2.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test Pod security context fs group\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/fsgroup/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/fsgroup/output-k8s.yaml\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/fsgroup/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/fsgroup/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test support for compose.yaml file\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/compose-file-support/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/compose-file-support/output-k8s.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test support for compose env interpolation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/compose-env-interpolation/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/compose-env-interpolation/output-k8s.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test support for compose env without interpolation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/compose-env-no-interpolation/compose.yaml convert --stdout --no-interpolate --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/compose-env-no-interpolation/output-k8s.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test configmap generated by env_file with variable interpolation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/envfile-interpolation/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_cmd=\"kompose  --provider=openshift -f  $KOMPOSE_ROOT/script/test/fixtures/envfile-interpolation/compose.yaml  convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/envfile-interpolation/output-k8s.yaml\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/envfile-interpolation/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test support for subpath volume\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/vols-subpath/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/vols-subpath/output-k8s.yaml\"\nos_cmd=\"kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/vols-subpath/compose.yaml convert --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/vols-subpath/output-os.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test support for network policies generation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/network-policies/compose.yaml convert --generate-network-policies --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/network-policies/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test support for namespace generation\nk8s_cmd=\"kompose -f ./script/test/fixtures/namespace/compose.yaml convert --stdout --with-kompose-annotation=false -n web\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/namespace/output-k8s.yaml\"\nos_cmd=\"kompose -f ./script/test/fixtures/namespace/compose.yaml convert --stdout --with-kompose-annotation=false -n web --provider openshift\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/namespace/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test support for read only root fs\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/read-only/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/read-only/output-k8s.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/read-only/compose.yaml convert --stdout --with-kompose-annotation=false --provider openshift\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/read-only/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test env_file support\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/env/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/env/output-k8s.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/env/compose.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/env/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# disabled until FormatEnvName can take into account conflicting/duplicate file names\n# Test env_file support for multiple env_file with the same name from different dirs\n# k8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/env-multiple/compose.yaml convert --stdout --with-kompose-annotation=false\"\n# k8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/env-multiple/output-k8s.yaml\"\n# os_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/env-multiple/compose.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\n# os_output=\"$KOMPOSE_ROOT/script/test/fixtures/env-multiple/output-os.yaml\"\n# convert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n# convert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test that if we have no profile a warning should raised\ncmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/no-profile-warning/compose.yaml convert\"\nconvert::expect_warning \"$cmd\" \"No service selected. The profile specified in services of your compose yaml may not exist.\" || exit 1\n\n# Test COMPOSE_FILE env variable is honored\nexport COMPOSE_FILE=\"$KOMPOSE_ROOT/script/test/fixtures/compose-file-env-variable/compose.yaml $KOMPOSE_ROOT/script/test/fixtures/compose-file-env-variable/alternative-compose.yaml\"\nk8s_cmd=\"kompose convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/compose-file-env-variable/output-k8s.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test resources names lowercase\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/resources-lowercase/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/resources-lowercase/output-k8s.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/resources-lowercase/compose.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/resources-lowercase/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test resources to generate initcontainer\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/initcontainer/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/initcontainer/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test HPA\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/hpa/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/hpa/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n#Test auto configmaps from files/dir\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose-1.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-k8s-1.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose-1.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-os-1.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n#Test auto configmaps from files/dir\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose-2.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-k8s-2.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose-2.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-os-2.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n#Test auto configmaps from files/dir\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose-3.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-k8s-3.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose-3.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-os-3.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success_and_warning \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test network_mode: service:\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/network-mode-service/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/network-mode-service/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test env var with status\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/envvars-with-status/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/envvars-with-status/output-k8s.yaml\"\nos_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/envvars-with-status/compose.yaml convert --provider openshift --stdout --with-kompose-annotation=false\"\nos_output=\"$KOMPOSE_ROOT/script/test/fixtures/envvars-with-status/output-os.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\nconvert::expect_success \"$os_cmd\" \"$os_output\" || exit 1\n\n# Test label in compose.yaml appears in the output annotation\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/label/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/label/output-k8s.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n# Test deploy.labels in compose.yaml appears in the output\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/deploy/labels/compose.yaml convert --stdout --with-kompose-annotation=false\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/deploy/labels/output-k8s.yaml\"\nconvert::expect_success \"$k8s_cmd\" \"$k8s_output\" || exit 1\n\n\n# TEST the security context conversion in service groups\nk8s_cmd=\"kompose -f $KOMPOSE_ROOT/script/test/fixtures/security-contexts/compose.yaml convert --stdout --with-kompose-annotation=false --service-group-mode label\"\nk8s_output=\"$KOMPOSE_ROOT/script/test/fixtures/security-contexts/output-k8s.yaml\"\nconvert::expect_success_and_warning \"$k8s_cmd\" \"$k8s_output\" || exit 1\n"
  },
  {
    "path": "script/test/cmd/tests_push_image.sh",
    "content": "#!/bin/bash\n\n# Copyright 2017 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 pe#rmissions and\n# limitations under the License.\n\n# Here are tests for pushing image on authentication and custom registry.\n# These tests only work on local for authentication inconvenient.\n# Prerequisites:\n# * `docker.io` account and docker login successfully\n# * custom registry which login as well. Or a local hosted registry.\n# * `jq` installed\n\n# Variables\nTEMP_DIR=\"/tmp/kompose\"\nmkdir -p $TEMP_DIR\nmkdir -p \"$TEMP_DIR/build\"\n\nDOCKER_LOGIN_USER=\"lexcao\" # TODO change this to your account for pushing to docker.io\nCOMPOSE_FILE=\"$TEMP_DIR/docker-compose-push.yml\"\nBUILD_FILE=\"$TEMP_DIR/build/Dockerfile\"\nCUSTOM_REGISTRY=\"localhost:5000\" # TODO change this to your local registry\n\n# Custom compose file based on parameter\nbuild_file_content=\"FROM busybox\n                    RUN touch /test\"\necho \"$build_file_content\" >> \"$BUILD_FILE\"\n\ncompose_file_content=\"version: \\\"2\\\"\n\nservices:\n    foo:\n        build: \\\"./build\\\"\n        image: docker.io/$DOCKER_LOGIN_USER/foobar\"\n\necho \"$compose_file_content\" >> \"$COMPOSE_FILE\"\n\n# Some helper functions\nfunction get_docker_hub_tag() {\n  local image=$1\n  local tag=$2\n  curl \"https://hub.docker.com/v2/repositories/$image/tags/$tag/\" | jq\n}\n\nfunction get_custom_registry_tag() {\n  local image=$1\n  local tag=$2\n  curl \"http://$CUSTOM_REGISTRY/v2/$image/manifests/$tag\" -I\n}\n\n###################################################################################\ncmd=\"kompose convert -f $COMPOSE_FILE -o $TEMP_DIR/output_file --build=local --push-image=true\"\n\nprintf \"Push image without custom registry default to docker.io\\n\"\necho \"executing cmd '$cmd'\"\n$cmd\nprintf \"\\nVerify push success...\\n\"\nget_docker_hub_tag \"$DOCKER_LOGIN_USER/foobar\" \"latest\"\n\n#######\nprintf \"\\nPush image with custom registry\\n\"\ncmd=\"$cmd --push-image-registry=$CUSTOM_REGISTRY\"\necho \"executing cmd '$cmd'\"\n$cmd\n#kompose convert -f \"$COMPOSE_FILE\" -o \"$TEMP_DIR/output_file\" --build=local --push-image=true\nprintf \"\\nVerify push success...\\n\"\nget_custom_registry_tag \"$DOCKER_LOGIN_USER/foobar\" \"latest\"\n\n# Clean resource\nrm -rf $TEMP_DIR\n"
  },
  {
    "path": "script/test/cmd/update-e2e.sh",
    "content": "#!/bin/bash\n# HOW TO USE: \n# In your kompose director execute: UPDATE_OS=true UPDATE_K8S=false ./update-e2e.sh\n\n\nmake bin\n# Feel free to update this variable to match your current FS\nexport KOMPOSE_ROOT=$HOME/projects/kompose\n\nif $UPDATE_K8S ; then\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/v2.0/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/v2.0/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/v3.0/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/v3.0/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/deploy/placement/docker-compose-placement.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/deploy/placement/output-placement-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/docker-compose.yml convert --stdout --with-kompose-annotation=false --volumes=configMap > $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/docker-compose-withlabel.yml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-k8s-withlabel.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/docker-compose.yml convert --with-kompose-annotation=false --stdout --volumes emptyDir > $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-k8s-empty-vols-template.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/docker-compose.yml convert --with-kompose-annotation=false --stdout --emptyvols > $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose/compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/expose/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/service-group/compose.yaml convert --stdout --with-kompose-annotation=false --service-group-mode=volume >$KOMPOSE_ROOT/script/test/fixtures/service-group/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/first.yaml -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/second.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/multiple-files/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/healthcheck/docker-compose-healthcheck.yaml convert --stdout --service-group-mode=label --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/healthcheck/output-healthcheck-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/statefulset/docker-compose.yaml convert --stdout --with-kompose-annotation=false --controller statefulset > $KOMPOSE_ROOT/script/test/fixtures/statefulset/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/single-file-output/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/single-file-output/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/docker-compose-v1.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-k8s-v1.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/docker-compose-v2.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-k8s-v2.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/compose-file-support/compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/compose-file-support/output-k8s.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/env/docker-compose.yml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/env/output-k8s.yaml\nfi\n\nif $UPDATE_OS ; then\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/v2.0/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/v2.0/output-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/windows/output-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/v3.0/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/v3.0/output-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/deploy/placement/docker-compose-placement.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/deploy/placement/output-placement-os.yaml\n$KOMPOSE_ROOT/kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/docker-compose.yml convert --stdout --with-kompose-annotation=false --volumes=configMap > $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-os.yaml\n$KOMPOSE_ROOT/kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/docker-compose-withlabel.yml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/configmap-volume/output-os-withlabel.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/docker-compose.yml convert --with-kompose-annotation=false --stdout --volumes emptyDir > $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-os-empty-vols-template.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/docker-compose.yml convert --with-kompose-annotation=false --stdout --emptyvols > $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-os.yaml\n$KOMPOSE_ROOT/kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose/compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/expose/output-os.yaml\n$KOMPOSE_ROOT/kompose  --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/first.yaml -f $KOMPOSE_ROOT/script/test/fixtures/multiple-files/second.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/multiple-files/output-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/healthcheck/docker-compose-healthcheck.yaml convert --stdout --service-group-mode=label --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/healthcheck/output-healthcheck-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/statefulset/docker-compose.yaml convert --stdout --with-kompose-annotation=false --controller statefulset > $KOMPOSE_ROOT/script/test/fixtures/statefulset/output-os.yaml\n$KOMPOSE_ROOT/kompose  --provider=openshift -f  $KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/docker-compose.yaml  convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/multiple-type-volumes/output-os.yaml\n$KOMPOSE_ROOT/kompose  --provider=openshift -f  $KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/docker-compose.yaml  convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/envvars-interpolation/output-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/docker-compose.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/host-port-protocol/output-os.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/docker-compose-v1.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-os-v1.yaml\n$KOMPOSE_ROOT/kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/docker-compose-v2.yaml convert --stdout --with-kompose-annotation=false > $KOMPOSE_ROOT/script/test/fixtures/external-traffic-policy/output-os-v2.yaml\n$KOMPOSE_ROOT/kompose -f $KOMPOSE_ROOT/script/test/fixtures/env/docker-compose.yml convert --stdout --with-kompose-annotation=false --provider openshift > $KOMPOSE_ROOT/script/test/fixtures/env/output-os.yaml\nfi\n"
  },
  {
    "path": "script/test/fixtures/buildargs/README.md",
    "content": "## Compose Buildargs\n\n### Usage\n\nThe simplest thing to do:\n\n```bash\nexport $(cat envs)\n```\n\nTo customize the values edit `envs` file.\n"
  },
  {
    "path": "script/test/fixtures/buildargs/build/Dockerfile",
    "content": "FROM busybox\nRUN touch /test"
  },
  {
    "path": "script/test/fixtures/buildargs/compose.yaml",
    "content": "\nservices:\n    foo:\n        build: \n          context: \"./build\"\n          args:\n            NAME: web\n        command: \"sleep 3600\"\n    foo1:\n        build:\n          context: \"./build\"\n          args:\n            - NAME=web\n            - foo\n        command: \"sleep 3600\"\n"
  },
  {
    "path": "script/test/fixtures/buildargs/envs",
    "content": "foo=bar\n"
  },
  {
    "path": "script/test/fixtures/buildargs/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"foo\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"foo:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"foo\",\n                \"image\": \" \",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"foo\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/buildargs/build/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {\n            \"env\": [\n              {\n                \"name\": \"NAME\",\n                \"value\": \"web\"\n              }\n            ]\n          }\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"foo:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"foo1\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"foo1:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"foo1\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"foo1\",\n                \"image\": \" \",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo1\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"foo1\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/buildargs/build/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {\n            \"env\": [\n              {\n                \"name\": \"NAME\",\n                \"value\": \"web\"\n              },\n              {\n                \"name\": \"foo\",\n                \"value\": \"bar\"\n              }\n            ]\n          }\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"foo1:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/buildconfig/build/Dockerfile",
    "content": "FROM busybox\nRUN touch /test"
  },
  {
    "path": "script/test/fixtures/buildconfig/compose-build-no-image.yaml",
    "content": "\nservices:\n    foo:\n        build: \"./build\"\n"
  },
  {
    "path": "script/test/fixtures/buildconfig/compose-dockerfile.yaml",
    "content": "\nservices:\n    foo:\n        build:\n          context: .\n          dockerfile: build/Dockerfile\n        image: docker.io/cdrage/foobar\n"
  },
  {
    "path": "script/test/fixtures/buildconfig/compose-v3.yaml",
    "content": "\nservices:\n    foo:\n        build:\n            context: ./build\n            dockerfile: Dockerfile\n"
  },
  {
    "path": "script/test/fixtures/buildconfig/compose.yaml",
    "content": "\nservices:\n    foo:\n        build: \"./build\"\n        image: docker.io/cdrage/foobar\n"
  },
  {
    "path": "script/test/fixtures/change-in-volume/compose.yaml",
    "content": "services:\n  web:\n    image: flask_web      \n    command: python app.py\n    ports:\n     - \"5000:5000\"\n    volumes:\n     - code_volume:/code\n    links:\n     - redis\n  redis:\n    image: redis\n    labels:\n      kompose.service.type: headless\n\nvolumes:\n  code_volume:"
  },
  {
    "path": "script/test/fixtures/change-in-volume/output-k8s-empty-vols-template.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  clusterIP: None\n  ports:\n    - name: headless\n      port: 55555\n      targetPort: 0\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: redis\n          name: redis\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - args:\n            - python\n            - app.py\n          image: flask_web\n          name: web\n          ports:\n            - containerPort: 5000\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /code\n              name: code-volume\n      restartPolicy: Always\n      volumes:\n        - name: code-volume\n\n"
  },
  {
    "path": "script/test/fixtures/change-in-volume/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  clusterIP: None\n  ports:\n    - name: headless\n      port: 55555\n      targetPort: 0\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: redis\n          name: redis\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - args:\n            - python\n            - app.py\n          image: flask_web\n          name: web\n          ports:\n            - containerPort: 5000\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /code\n              name: code-volume\n      restartPolicy: Always\n      volumes:\n        - name: code-volume\n\n"
  },
  {
    "path": "script/test/fixtures/change-in-volume/output-os-empty-vols-template.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  clusterIP: None\n  ports:\n    - name: headless\n      port: 55555\n      targetPort: 0\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: ' '\n          name: redis\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - args:\n            - python\n            - app.py\n          image: ' '\n          name: web\n          ports:\n            - containerPort: 5000\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /code\n              name: code-volume\n      restartPolicy: Always\n      volumes:\n        - name: code-volume\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: flask_web\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/change-in-volume/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  clusterIP: None\n  ports:\n    - name: headless\n      port: 55555\n      targetPort: 0\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: ' '\n          name: redis\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - args:\n            - python\n            - app.py\n          image: ' '\n          name: web\n          ports:\n            - containerPort: 5000\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /code\n              name: code-volume\n      restartPolicy: Always\n      volumes:\n        - name: code-volume\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: flask_web\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/compose-env-interpolation/compose.yaml",
    "content": "\nservices:\n  foo:\n    labels:\n      kompose.image-pull-policy: \"${IMAGE_PULL_POLICY:-IfNotPresent}\"\n    build: .\n    ports:\n      - 80:80\n"
  },
  {
    "path": "script/test/fixtures/compose-env-interpolation/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: foo\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: foo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: foo\n    spec:\n      containers:\n        - image: foo\n          imagePullPolicy: IfNotPresent\n          name: foo\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/compose-env-no-interpolation/compose.yaml",
    "content": "\nservices:\n  foo:\n    image: ${DOCKER_REGISTRY-}foo:${IMAGE_TAG:-latest}\n    build: .\n    environment:\n      - VERSION=${IMAGE_TAG:-latest}\n    ports:\n      - 80:80\n"
  },
  {
    "path": "script/test/fixtures/compose-env-no-interpolation/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: foo\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: foo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: foo\n    spec:\n      containers:\n        - env:\n            - name: VERSION\n              value: ${IMAGE_TAG:-latest}\n          image: ${DOCKER_REGISTRY-}foo:${IMAGE_TAG:-latest}\n          name: foo\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/compose-file-env-variable/alternative-compose.yaml",
    "content": "services:\n  alpine:\n    image: alpine\n    ports:\n      - 80:80\n\n"
  },
  {
    "path": "script/test/fixtures/compose-file-env-variable/compose.yaml",
    "content": "services:\n  debian:\n    image: debian\n    ports:\n      - 80:80\n"
  },
  {
    "path": "script/test/fixtures/compose-file-env-variable/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: alpine\n  name: alpine\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: alpine\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: debian\n  name: debian\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: debian\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: alpine\n  name: alpine\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: alpine\n  template:\n    metadata:\n      labels:\n        io.kompose.service: alpine\n    spec:\n      containers:\n        - image: alpine\n          name: alpine\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: debian\n  name: debian\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: debian\n  template:\n    metadata:\n      labels:\n        io.kompose.service: debian\n    spec:\n      containers:\n        - image: debian\n          name: debian\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/compose-file-support/compose.yaml",
    "content": "services:\n  web:\n    image: nginx:latest\n    ports:\n    - \"80:80\"\n"
  },
  {
    "path": "script/test/fixtures/compose-file-support/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: web\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx:latest\n          name: web\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/compose-config-long-warning.yaml",
    "content": "services:\n  redis:\n    image: redis:latest\n    deploy:\n      replicas: 1\n    configs:\n      - source: my_config\n        target: /redis_config\n        uid: '103'\n        gid: '103'\n        mode: 0440\nconfigs:\n  my_config:\n    file: ./my_config.txt\n  my_other_config:\n    external: true"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/compose-config-long.yaml",
    "content": "services:\n  redis:\n    image: redis:latest\n    deploy:\n      replicas: 1\n    configs:\n      - source: my_config\n        target: /redis_config\n        uid: '103'\n        gid: '103'\n        mode: 0440\nconfigs:\n  my_config:\n    file: ./my_config.txt"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/compose-config-short-warning.yaml",
    "content": "services:\n  redis:\n    image: redis:latest\n    deploy:\n      replicas: 1\n    configs:\n      - my_config\n      - my_other_config\nconfigs:\n  my_config:\n    file: ./my_config.txt\n  my_other_config:\n    external: true"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/compose-config-short.yaml",
    "content": "services:\n  redis:\n    image: redis:latest\n    deploy:\n      replicas: 1\n    configs:\n      - my_config\nconfigs:\n  my_config:\n    file: ./my_config.txt"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/compose-endpoint-mode-1.yaml",
    "content": "\nservices:\n  wordpress:\n    image: wordpress\n    ports:\n      - \"8080:80\"\n    deploy:\n      mode: replicated\n      replicas: 2\n      endpoint_mode: vip"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/compose-endpoint-mode-2.yaml",
    "content": "\nservices:\n  wordpress:\n    image: wordpress\n    ports:\n      - \"8080:80\"\n    deploy:\n      mode: replicated\n      replicas: 2\n      endpoint_mode: dnsrr"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/my_config.txt",
    "content": "aaaa"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-k8s-config-long-warning.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"data\": {\n        \"my_config.txt\": \"aaaa\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/redis_config\",\n                    \"name\": \"my-config\",\n                    \"subPath\": \"redis_config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"defaultMode\": 288,\n                  \"items\": [\n                    {\n                      \"key\": \"my_config.txt\",\n                      \"path\": \"redis_config\"\n                    }\n                  ],\n                  \"name\": \"my-config\"\n                },\n                \"name\": \"my-config\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-k8s-config-long.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"data\": {\n        \"my_config.txt\": \"aaaa\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/redis_config\",\n                    \"name\": \"my-config\",\n                    \"subPath\": \"redis_config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"defaultMode\": 288,\n                  \"items\": [\n                    {\n                      \"key\": \"my_config.txt\",\n                      \"path\": \"redis_config\"\n                    }\n                  ],\n                  \"name\": \"my-config\"\n                },\n                \"name\": \"my-config\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-k8s-config-short-warning.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"data\": {\n        \"my_config.txt\": \"aaaa\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/my_config\",\n                    \"name\": \"my-config\",\n                    \"subPath\": \"my_config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"items\": [\n                    {\n                      \"key\": \"my_config.txt\",\n                      \"path\": \"my_config\"\n                    }\n                  ],\n                  \"name\": \"my-config\"\n                },\n                \"name\": \"my-config\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-k8s-config-short.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"data\": {\n        \"my_config.txt\": \"aaaa\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/my_config\",\n                    \"name\": \"my-config\",\n                    \"subPath\": \"my_config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"items\": [\n                    {\n                      \"key\": \"my_config.txt\",\n                      \"path\": \"my_config\"\n                    }\n                  ],\n                  \"name\": \"my-config\"\n                },\n                \"name\": \"my-config\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-k8s-endpoint-mode-1.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"name\": \"wordpress\"\n      },\n      \"spec\": {\n        \"replicas\": 2,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"wordpress\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"wordpress\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"wordpress\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"wordpress\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-k8s-endpoint-mode-2.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"name\": \"wordpress\"\n      },\n      \"spec\": {\n        \"replicas\": 2,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"wordpress\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"wordpress\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"wordpress\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"wordpress\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-os-config-long.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"data\": {\n        \"my_config.txt\": \"aaaa\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"my-config\",\n                \"configMap\": {\n                  \"name\": \"my-config\",\n                  \"items\": [\n                    {\n                      \"key\": \"my_config.txt\",\n                      \"path\": \"redis_config\"\n                    }\n                  ],\n                  \"defaultMode\": 288\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"my-config\",\n                    \"mountPath\": \"/redis_config\",\n                    \"subPath\": \"redis_config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-os-config-short.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"data\": {\n        \"my_config.txt\": \"aaaa\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"my-config\",\n                \"configMap\": {\n                  \"name\": \"my-config\",\n                  \"items\": [\n                    {\n                      \"key\": \"my_config.txt\",\n                      \"path\": \"my_config\"\n                    }\n                  ]\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"my-config\",\n                    \"mountPath\": \"/my_config\",\n                    \"subPath\": \"my_config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/compose-v3.3-test/output-os-mode-1.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"wordpress\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"wordpress:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 2,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"wordpress\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"wordpress\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"wordpress\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/configmap/bar.env",
    "content": "# Multi-line test\nFOO=BAR\nBAR=FOO\n"
  },
  {
    "path": "script/test/fixtures/configmap/compose.yaml",
    "content": "\nservices:\n  redis:\n    image: 'bitnami/redis:latest'\n    environment:\n      - ALLOW_EMPTY_PASSWORD=no\n    # Env file will override environment / warn!\n    env_file:\n      - \"foo.env\"\n      - bar.env\n    labels:\n      kompose.service.type: nodeport\n    ports:\n      - '6379:6379'\n"
  },
  {
    "path": "script/test/fixtures/configmap/foo.env",
    "content": "# Test comment!\nALLOW_EMPTY_PASSWORD=yes\n"
  },
  {
    "path": "script/test/fixtures/configmap/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"nodeport\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"nodeport\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"nodeport\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"valueFrom\": {\n                      \"configMapKeyRef\": {\n                        \"key\": \"ALLOW_EMPTY_PASSWORD\",\n                        \"name\": \"foo-env\"\n                      }\n                    }\n                  },\n                  {\n                    \"name\": \"BAR\",\n                    \"valueFrom\": {\n                      \"configMapKeyRef\": {\n                        \"key\": \"BAR\",\n                        \"name\": \"bar-env\"\n                      }\n                    }\n                  },\n                  {\n                    \"name\": \"FOO\",\n                    \"valueFrom\": {\n                      \"configMapKeyRef\": {\n                        \"key\": \"FOO\",\n                        \"name\": \"bar-env\"\n                      }\n                    }\n                  }\n                ],\n                \"image\": \"bitnami/redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-env\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-foo-env\"\n        }\n      },\n      \"data\": {\n        \"ALLOW_EMPTY_PASSWORD\": \"yes\"\n      }\n    },\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar-env\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-bar-env\"\n        }\n      },\n      \"data\": {\n        \"BAR\": \"FOO\",\n        \"FOO\": \"BAR\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/auth.txt",
    "content": "content from file auth.txt\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/certs/cert1.pem",
    "content": "content of file cert1.pem\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/certs-level1/certs-level2/certs-level3/cert2.pem",
    "content": "content from file cert2.pem"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/compose-1.yaml",
    "content": "services:\n  busy:\n    image: busybox\n    ports:\n      - \"8081:8080\"\n      - \"8026:8025\"\n    volumes:\n      - ./certs:/certs\n      - ./auth.txt:/auth.txt\n      - ./users.php:/users.php:ro\n    command:\n      [\n        \"/bin/sh\", \n        \"-c\", \n        \"cat /auth.txt /users.php /certs/cert1.pem\"\n      ]\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/compose-2.yaml",
    "content": "services:\n  busy:\n    image: busybox\n    ports:\n      - \"8081:8080\"\n      - \"8026:8025\"\n    volumes:\n      - ./certs:/certs\n      - ./certs-level1/certs-level2/certs-level3/cert2.pem:/certs/cert2.pem\n      - ./auth.txt:/auth.txt\n      - ./users.php:/users.php:ro\n    command:\n      [\n        \"/bin/sh\", \n        \"-c\", \n        \"cat /auth.txt /users.php /certs/cert1.pem /certs/cert2.pem\"\n      ]\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/compose-3.yaml",
    "content": "services:\n  busy:\n    image: busybox\n    ports:\n      - \"8081:8080\"\n      - \"8026:8025\"\n    volumes:\n      - /tmp:/tmp:ro"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/output-k8s-1.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  ports:\n    - name: \"8081\"\n      port: 8081\n      targetPort: 8080\n    - name: \"8026\"\n      port: 8026\n      targetPort: 8025\n  selector:\n    io.kompose.service: busy\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: busy\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: busy\n    spec:\n      containers:\n        - args:\n            - /bin/sh\n            - -c\n            - cat /auth.txt /users.php /certs/cert1.pem\n          image: busybox\n          name: busy\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n            - containerPort: 8025\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /certs\n              name: busy-cm0\n            - mountPath: /auth.txt\n              name: busy-cm1\n              subPath: auth.txt\n            - mountPath: /users.php\n              name: busy-cm2\n              subPath: users.php\n              readOnly: true\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: busy-cm0\n          name: busy-cm0\n        - configMap:\n            items:\n              - key: auth.txt\n                path: auth.txt\n            name: busy-cm1\n          name: busy-cm1\n        - configMap:\n            items:\n              - key: users.php\n                path: users.php\n            name: busy-cm2\n          name: busy-cm2\n\n---\napiVersion: v1\ndata:\n  cert1.pem: |\n    content of file cert1.pem\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy-cm0\n\n---\napiVersion: v1\ndata:\n  auth.txt: |\n    content from file auth.txt\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm1\n\n---\napiVersion: v1\ndata:\n  users.php: |\n    content from file users.php\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm2\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/output-k8s-2.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  ports:\n    - name: \"8081\"\n      port: 8081\n      targetPort: 8080\n    - name: \"8026\"\n      port: 8026\n      targetPort: 8025\n  selector:\n    io.kompose.service: busy\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: busy\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: busy\n    spec:\n      containers:\n        - args:\n            - /bin/sh\n            - -c\n            - cat /auth.txt /users.php /certs/cert1.pem /certs/cert2.pem\n          image: busybox\n          name: busy\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n            - containerPort: 8025\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /certs\n              name: busy-cm0\n            - mountPath: /certs/cert2.pem\n              name: busy-cm1\n              subPath: cert2.pem\n            - mountPath: /auth.txt\n              name: busy-cm2\n              subPath: auth.txt\n            - mountPath: /users.php\n              name: busy-cm3\n              readOnly: true\n              subPath: users.php\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: busy-cm0\n          name: busy-cm0\n        - configMap:\n            items:\n              - key: cert2.pem\n                path: cert2.pem\n            name: busy-cm1\n          name: busy-cm1\n        - configMap:\n            items:\n              - key: auth.txt\n                path: auth.txt\n            name: busy-cm2\n          name: busy-cm2\n        - configMap:\n            items:\n              - key: users.php\n                path: users.php\n            name: busy-cm3\n          name: busy-cm3\n\n---\napiVersion: v1\ndata:\n  cert1.pem: |\n    content of file cert1.pem\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy-cm0\n\n---\napiVersion: v1\ndata:\n  cert2.pem: content from file cert2.pem\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm1\n\n---\napiVersion: v1\ndata:\n  auth.txt: |\n    content from file auth.txt\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm2\n\n---\napiVersion: v1\ndata:\n  users.php: |\n    content from file users.php\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm3\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/output-k8s-3.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  ports:\n    - name: \"8081\"\n      port: 8081\n      targetPort: 8080\n    - name: \"8026\"\n      port: 8026\n      targetPort: 8025\n  selector:\n    io.kompose.service: busy\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: busy\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: busy\n    spec:\n      containers:\n        - image: busybox\n          name: busy\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n            - containerPort: 8025\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/output-os-1.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  ports:\n    - name: \"8081\"\n      port: 8081\n      targetPort: 8080\n    - name: \"8026\"\n      port: 8026\n      targetPort: 8025\n  selector:\n    io.kompose.service: busy\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: busy\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: busy\n    spec:\n      containers:\n        - args:\n            - /bin/sh\n            - -c\n            - cat /auth.txt /users.php /certs/cert1.pem\n          image: ' '\n          name: busy\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n            - containerPort: 8025\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /certs\n              name: busy-cm0\n            - mountPath: /auth.txt\n              name: busy-cm1\n              subPath: auth.txt\n            - mountPath: /users.php\n              name: busy-cm2\n              readOnly: true\n              subPath: users.php\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: busy-cm0\n          name: busy-cm0\n        - configMap:\n            items:\n              - key: auth.txt\n                path: auth.txt\n            name: busy-cm1\n          name: busy-cm1\n        - configMap:\n            items:\n              - key: users.php\n                path: users.php\n            name: busy-cm2\n          name: busy-cm2\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - busy\n        from:\n          kind: ImageStreamTag\n          name: busy:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: busybox\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\ndata:\n  cert1.pem: |\n    content of file cert1.pem\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy-cm0\n\n---\napiVersion: v1\ndata:\n  auth.txt: |\n    content from file auth.txt\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm1\n\n---\napiVersion: v1\ndata:\n  users.php: |\n    content from file users.php\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm2\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/output-os-2.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  ports:\n    - name: \"8081\"\n      port: 8081\n      targetPort: 8080\n    - name: \"8026\"\n      port: 8026\n      targetPort: 8025\n  selector:\n    io.kompose.service: busy\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: busy\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: busy\n    spec:\n      containers:\n        - args:\n            - /bin/sh\n            - -c\n            - cat /auth.txt /users.php /certs/cert1.pem /certs/cert2.pem\n          image: ' '\n          name: busy\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n            - containerPort: 8025\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /certs\n              name: busy-cm0\n            - mountPath: /certs/cert2.pem\n              name: busy-cm1\n              subPath: cert2.pem\n            - mountPath: /auth.txt\n              name: busy-cm2\n              subPath: auth.txt\n            - mountPath: /users.php\n              name: busy-cm3\n              readOnly: true\n              subPath: users.php\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: busy-cm0\n          name: busy-cm0\n        - configMap:\n            items:\n              - key: cert2.pem\n                path: cert2.pem\n            name: busy-cm1\n          name: busy-cm1\n        - configMap:\n            items:\n              - key: auth.txt\n                path: auth.txt\n            name: busy-cm2\n          name: busy-cm2\n        - configMap:\n            items:\n              - key: users.php\n                path: users.php\n            name: busy-cm3\n          name: busy-cm3\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - busy\n        from:\n          kind: ImageStreamTag\n          name: busy:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: busybox\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\ndata:\n  cert1.pem: |\n    content of file cert1.pem\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy-cm0\n\n---\napiVersion: v1\ndata:\n  cert2.pem: content from file cert2.pem\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm1\n\n---\napiVersion: v1\ndata:\n  auth.txt: |\n    content from file auth.txt\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm2\n\n---\napiVersion: v1\ndata:\n  users.php: |\n    content from file users.php\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: busy\n  name: busy-cm3\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/output-os-3.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  ports:\n    - name: \"8081\"\n      port: 8081\n      targetPort: 8080\n    - name: \"8026\"\n      port: 8026\n      targetPort: 8025\n  selector:\n    io.kompose.service: busy\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: busy\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: busy\n    spec:\n      containers:\n        - image: ' '\n          name: busy\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n            - containerPort: 8025\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - busy\n        from:\n          kind: ImageStreamTag\n          name: busy:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: busy\n  name: busy\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: busybox\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-file-configs/users.php",
    "content": "content from file users.php\n"
  },
  {
    "path": "script/test/fixtures/configmap-pod/bar.env",
    "content": "# Multi-line test\nFOO=BAR\nBAR=FOO\n"
  },
  {
    "path": "script/test/fixtures/configmap-pod/compose.yaml",
    "content": "\nservices:\n  redis:\n    image: 'bitnami/redis:latest'\n    environment:\n      - ALLOW_EMPTY_PASSWORD=no\n    # Env file will override environment / warn!\n    env_file:\n      - \"foo.env\"\n      - bar.env\n    labels:\n      kompose.service.type: nodeport\n    ports:\n      - '6379:6379'\n    restart: \"no\"\n"
  },
  {
    "path": "script/test/fixtures/configmap-pod/foo.env",
    "content": "# Test comment!\nALLOW_EMPTY_PASSWORD=yes\n"
  },
  {
    "path": "script/test/fixtures/configmap-pod/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n  type: NodePort\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  containers:\n    - envFrom:\n        - configMapRef:\n            name: foo-env\n        - configMapRef:\n            name: bar-env\n      image: bitnami/redis:latest\n      name: redis\n      ports:\n        - containerPort: 6379\n          protocol: TCP\n  restartPolicy: Never\n\n---\napiVersion: v1\ndata:\n  ALLOW_EMPTY_PASSWORD: \"yes\"\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: redis-foo-env\n  name: foo-env\n\n---\napiVersion: v1\ndata:\n  BAR: FOO\n  FOO: BAR\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: redis-bar-env\n  name: bar-env\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-pod/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n  type: NodePort\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  containers:\n    - envFrom:\n        - configMapRef:\n            name: foo-env\n        - configMapRef:\n            name: bar-env\n      image: bitnami/redis:latest\n      name: redis\n      ports:\n        - containerPort: 6379\n          protocol: TCP\n  restartPolicy: Never\n\n---\napiVersion: v1\ndata:\n  ALLOW_EMPTY_PASSWORD: \"yes\"\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: redis-foo-env\n  name: foo-env\n\n---\napiVersion: v1\ndata:\n  BAR: FOO\n  FOO: BAR\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: redis-bar-env\n  name: bar-env\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/compose-withlabel.yaml",
    "content": "services:\n  web:\n    image: nginx\n    volumes:\n      - ./tls:/etc/tls\n      - ./tls/a.key:/etc/test-a-key.key\n    labels:\n      kompose.volume.type: configMap\n  db:\n    image: mysql\n    volumes:\n      - ./configs.tar:/data/configs.tar\n    labels:\n      kompose.volume.type: configMap\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/compose.yaml",
    "content": "services:\n  web:\n    image: nginx\n    volumes:\n      - ./tls:/etc/tls\n      - ./tls/a.key:/etc/test-a-key.key\n  db:\n    image: mysql\n    volumes:\n      - ./configs.tar:/data/configs.tar\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/output-k8s-withlabel.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: mysql\n          name: db\n          volumeMounts:\n            - mountPath: /data/configs.tar\n              name: db-cm0\n              subPath: configs.tar\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            items:\n              - key: configs.tar\n                path: configs.tar\n            name: db-cm0\n          name: db-cm0\n\n---\napiVersion: v1\nbinaryData:\n  configs.tar: SDRzSUFId3pMVjhBQSsxV3pXc1RRUlFmQ3lMdVJRL2lRVkNHVmFsSVBtWm12N0tXRkFvRksxSU1UU29GVjhLWVRHc2tYK3h1WkV1SjlPaS80TkdiWjIrQ2wrSk4vQ3M4OTZ4WFo3K3lTWGFEc1NZcEpmdExabWJmNC9mbXZielpOeThsNm13eFdtZG12dFpwN3pjT0xEQjdJSVEwUllGQTh4Q3RLQUJHQkdKSnd4S1JzS0xKRUJGRVpCVkFadzZ4eE5DemJHcnlVTXl1MVdVbU0ra0Uzdk1uTzVYZDhvYXgyV25SUmh2dVdzd2N5WlgvVStCZ3ZTREFCWGpRcUJleHJoTkZ3YXFHQks3cGVScFoxeVFkUzdJZ0lkaXlHeTFXeElxdWFycFdJQ2lueWhqcC9Lc0w1LzBMVXZ3UGdxclB6OU5IV1AvSC9ObFdQNzF6MTdmZlRuK2hDT1AxajVBQ29ETFBvRUlzZWYySDUxOGE5SUZjdFU1dG1udGpkZG96OHNIem9jcnk1UHNmY1dIMC9JbWt5T245dndoTWMvOFRMZkgreHdVbHZmd3ZPc0w2bjMzVlJ3anIveGdrMy84eWtjZnJIeEgrL3cvTlBKSUVMSG45ZzhzM3I0QVZBTFpwRFQ0cnd6MFl3TldCcTN3UVBuN3l3ZVZMTjZiYmNxTlMyZkdmUEl1dmZPeU5VVllDL1hVQWJ0VTZyUnp0ZHBzczE2U1czYk5ZbmIrSzdHNnBISEIvOExFRndMV0kxNksxSmxlZWttelZKYnkzbjk3M3FYY2Uvbjc5NE9Qai91ZnZINm9uWDA1dW56VXB5NE40LzUvOVBYQ0cvcy9GdFA4dkFtbi9YMjZFOVQrLzd2L1gvbzlsTkY3L1dNVlMydjhYZ1JjQ2hFZUMyL0ZGeHhFZlFZd3lvZVRKN2lwT3BmSWVNKzY4Rmd3SERxWTFMR2RITmQ0MG9nL1VlY2NRTTlEd3RqVDQzdjZUVTNWOFJYL1l0ZWZidDh1dXIzUHF2WndoK2diUXA3c2ZPT1ExTXhYWkR3NW1qRVEyRHpHaVJ6dTdVVTNlUFRtZUFOeldjR0syc1p3RjgzaWdtU1RIM0hpVEhnNmJRY2ZMYldETEpXaTBvLzJQM0xrZitmTHlEWXR3ZGVoMEJoNVh4ODdmZjROODJYMkpQTEgvajV3WUswNmpOYnZSYWROWFRiYk5xTlV6V2VXd3l4S3NTRklBNGxBdUJ0a1hPYVV2dkR6dk1reVJJa1dLaGVNUENNUUc3Z0FjQUFBPQ==\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: db\n  name: db-cm0\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx\n          name: web\n          volumeMounts:\n            - mountPath: /etc/tls\n              name: web-cm0\n            - mountPath: /etc/test-a-key.key\n              name: web-cm1\n              subPath: test-a-key.key\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: web-cm0\n          name: web-cm0\n        - configMap:\n            items:\n              - key: a.key\n                path: test-a-key.key\n            name: web-cm1\n          name: web-cm1\n\n---\napiVersion: v1\ndata:\n  a.crt: test-crt-data...\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web-cm0\n\n---\napiVersion: v1\ndata:\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: web\n  name: web-cm1\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: mysql\n          name: db\n          volumeMounts:\n            - mountPath: /data/configs.tar\n              name: db-cm0\n              subPath: configs.tar\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            items:\n              - key: configs.tar\n                path: configs.tar\n            name: db-cm0\n          name: db-cm0\n\n\n---\napiVersion: v1\nbinaryData:\n  configs.tar: SDRzSUFId3pMVjhBQSsxV3pXc1RRUlFmQ3lMdVJRL2lRVkNHVmFsSVBtWm12N0tXRkFvRksxSU1UU29GVjhLWVRHc2tYK3h1WkV1SjlPaS80TkdiWjIrQ2wrSk4vQ3M4OTZ4WFo3K3lTWGFEc1NZcEpmdExabWJmNC9mbXZielpOeThsNm13eFdtZG12dFpwN3pjT0xEQjdJSVEwUllGQTh4Q3RLQUJHQkdKSnd4S1JzS0xKRUJGRVpCVkFadzZ4eE5DemJHcnlVTXl1MVdVbU0ra0Uzdk1uTzVYZDhvYXgyV25SUmh2dVdzd2N5WlgvVStCZ3ZTREFCWGpRcUJleHJoTkZ3YXFHQks3cGVScFoxeVFkUzdJZ0lkaXlHeTFXeElxdWFycFdJQ2lueWhqcC9Lc0w1LzBMVXZ3UGdxclB6OU5IV1AvSC9ObFdQNzF6MTdmZlRuK2hDT1AxajVBQ29ETFBvRUlzZWYySDUxOGE5SUZjdFU1dG1udGpkZG96OHNIem9jcnk1UHNmY1dIMC9JbWt5T245dndoTWMvOFRMZkgreHdVbHZmd3ZPc0w2bjMzVlJ3anIveGdrMy84eWtjZnJIeEgrL3cvTlBKSUVMSG45ZzhzM3I0QVZBTFpwRFQ0cnd6MFl3TldCcTN3UVBuN3l3ZVZMTjZiYmNxTlMyZkdmUEl1dmZPeU5VVllDL1hVQWJ0VTZyUnp0ZHBzczE2U1czYk5ZbmIrSzdHNnBISEIvOExFRndMV0kxNksxSmxlZWttelZKYnkzbjk3M3FYY2Uvbjc5NE9Qai91ZnZINm9uWDA1dW56VXB5NE40LzUvOVBYQ0cvcy9GdFA4dkFtbi9YMjZFOVQrLzd2L1gvbzlsTkY3L1dNVlMydjhYZ1JjQ2hFZUMyL0ZGeHhFZlFZd3lvZVRKN2lwT3BmSWVNKzY4Rmd3SERxWTFMR2RITmQ0MG9nL1VlY2NRTTlEd3RqVDQzdjZUVTNWOFJYL1l0ZWZidDh1dXIzUHF2WndoK2diUXA3c2ZPT1ExTXhYWkR3NW1qRVEyRHpHaVJ6dTdVVTNlUFRtZUFOeldjR0syc1p3RjgzaWdtU1RIM0hpVEhnNmJRY2ZMYldETEpXaTBvLzJQM0xrZitmTHlEWXR3ZGVoMEJoNVh4ODdmZjROODJYMkpQTEgvajV3WUswNmpOYnZSYWROWFRiYk5xTlV6V2VXd3l4S3NTRklBNGxBdUJ0a1hPYVV2dkR6dk1reVJJa1dLaGVNUENNUUc3Z0FjQUFBPQ==\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: db\n  name: db-cm0\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx\n          name: web\n          volumeMounts:\n            - mountPath: /etc/tls\n              name: web-cm0\n            - mountPath: /etc/test-a-key.key\n              name: web-cm1\n              subPath: test-a-key.key\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: web-cm0\n          name: web-cm0\n        - configMap:\n            items:\n              - key: a.key\n                path: test-a-key.key\n            name: web-cm1\n          name: web-cm1\n\n---\napiVersion: v1\ndata:\n  a.crt: test-crt-data...\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web-cm0\n\n---\napiVersion: v1\ndata:\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: web\n  name: web-cm1\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/output-os-withlabel.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: ' '\n          name: db\n          volumeMounts:\n            - mountPath: /data/configs.tar\n              name: db-cm0\n              subPath: configs.tar\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            items:\n              - key: configs.tar\n                path: configs.tar\n            name: db-cm0\n          name: db-cm0\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - db\n        from:\n          kind: ImageStreamTag\n          name: db:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: mysql\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nbinaryData:\n  configs.tar: SDRzSUFId3pMVjhBQSsxV3pXc1RRUlFmQ3lMdVJRL2lRVkNHVmFsSVBtWm12N0tXRkFvRksxSU1UU29GVjhLWVRHc2tYK3h1WkV1SjlPaS80TkdiWjIrQ2wrSk4vQ3M4OTZ4WFo3K3lTWGFEc1NZcEpmdExabWJmNC9mbXZielpOeThsNm13eFdtZG12dFpwN3pjT0xEQjdJSVEwUllGQTh4Q3RLQUJHQkdKSnd4S1JzS0xKRUJGRVpCVkFadzZ4eE5DemJHcnlVTXl1MVdVbU0ra0Uzdk1uTzVYZDhvYXgyV25SUmh2dVdzd2N5WlgvVStCZ3ZTREFCWGpRcUJleHJoTkZ3YXFHQks3cGVScFoxeVFkUzdJZ0lkaXlHeTFXeElxdWFycFdJQ2lueWhqcC9Lc0w1LzBMVXZ3UGdxclB6OU5IV1AvSC9ObFdQNzF6MTdmZlRuK2hDT1AxajVBQ29ETFBvRUlzZWYySDUxOGE5SUZjdFU1dG1udGpkZG96OHNIem9jcnk1UHNmY1dIMC9JbWt5T245dndoTWMvOFRMZkgreHdVbHZmd3ZPc0w2bjMzVlJ3anIveGdrMy84eWtjZnJIeEgrL3cvTlBKSUVMSG45ZzhzM3I0QVZBTFpwRFQ0cnd6MFl3TldCcTN3UVBuN3l3ZVZMTjZiYmNxTlMyZkdmUEl1dmZPeU5VVllDL1hVQWJ0VTZyUnp0ZHBzczE2U1czYk5ZbmIrSzdHNnBISEIvOExFRndMV0kxNksxSmxlZWttelZKYnkzbjk3M3FYY2Uvbjc5NE9Qai91ZnZINm9uWDA1dW56VXB5NE40LzUvOVBYQ0cvcy9GdFA4dkFtbi9YMjZFOVQrLzd2L1gvbzlsTkY3L1dNVlMydjhYZ1JjQ2hFZUMyL0ZGeHhFZlFZd3lvZVRKN2lwT3BmSWVNKzY4Rmd3SERxWTFMR2RITmQ0MG9nL1VlY2NRTTlEd3RqVDQzdjZUVTNWOFJYL1l0ZWZidDh1dXIzUHF2WndoK2diUXA3c2ZPT1ExTXhYWkR3NW1qRVEyRHpHaVJ6dTdVVTNlUFRtZUFOeldjR0syc1p3RjgzaWdtU1RIM0hpVEhnNmJRY2ZMYldETEpXaTBvLzJQM0xrZitmTHlEWXR3ZGVoMEJoNVh4ODdmZjROODJYMkpQTEgvajV3WUswNmpOYnZSYWROWFRiYk5xTlV6V2VXd3l4S3NTRklBNGxBdUJ0a1hPYVV2dkR6dk1reVJJa1dLaGVNUENNUUc3Z0FjQUFBPQ==\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: db\n  name: db-cm0\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: ' '\n          name: web\n          volumeMounts:\n            - mountPath: /etc/tls\n              name: web-cm0\n            - mountPath: /etc/test-a-key.key\n              name: web-cm1\n              subPath: test-a-key.key\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: web-cm0\n          name: web-cm0\n        - configMap:\n            items:\n              - key: a.key\n                path: test-a-key.key\n            name: web-cm1\n          name: web-cm1\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\ndata:\n  a.crt: test-crt-data...\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web-cm0\n\n---\napiVersion: v1\ndata:\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: web\n  name: web-cm1\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/output-os.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: ' '\n          name: db\n          volumeMounts:\n            - mountPath: /data/configs.tar\n              name: db-cm0\n              subPath: configs.tar\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            items:\n              - key: configs.tar\n                path: configs.tar\n            name: db-cm0\n          name: db-cm0\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - db\n        from:\n          kind: ImageStreamTag\n          name: db:latest\n      type: ImageChange\n\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: mysql\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nbinaryData:\n  configs.tar: SDRzSUFId3pMVjhBQSsxV3pXc1RRUlFmQ3lMdVJRL2lRVkNHVmFsSVBtWm12N0tXRkFvRksxSU1UU29GVjhLWVRHc2tYK3h1WkV1SjlPaS80TkdiWjIrQ2wrSk4vQ3M4OTZ4WFo3K3lTWGFEc1NZcEpmdExabWJmNC9mbXZielpOeThsNm13eFdtZG12dFpwN3pjT0xEQjdJSVEwUllGQTh4Q3RLQUJHQkdKSnd4S1JzS0xKRUJGRVpCVkFadzZ4eE5DemJHcnlVTXl1MVdVbU0ra0Uzdk1uTzVYZDhvYXgyV25SUmh2dVdzd2N5WlgvVStCZ3ZTREFCWGpRcUJleHJoTkZ3YXFHQks3cGVScFoxeVFkUzdJZ0lkaXlHeTFXeElxdWFycFdJQ2lueWhqcC9Lc0w1LzBMVXZ3UGdxclB6OU5IV1AvSC9ObFdQNzF6MTdmZlRuK2hDT1AxajVBQ29ETFBvRUlzZWYySDUxOGE5SUZjdFU1dG1udGpkZG96OHNIem9jcnk1UHNmY1dIMC9JbWt5T245dndoTWMvOFRMZkgreHdVbHZmd3ZPc0w2bjMzVlJ3anIveGdrMy84eWtjZnJIeEgrL3cvTlBKSUVMSG45ZzhzM3I0QVZBTFpwRFQ0cnd6MFl3TldCcTN3UVBuN3l3ZVZMTjZiYmNxTlMyZkdmUEl1dmZPeU5VVllDL1hVQWJ0VTZyUnp0ZHBzczE2U1czYk5ZbmIrSzdHNnBISEIvOExFRndMV0kxNksxSmxlZWttelZKYnkzbjk3M3FYY2Uvbjc5NE9Qai91ZnZINm9uWDA1dW56VXB5NE40LzUvOVBYQ0cvcy9GdFA4dkFtbi9YMjZFOVQrLzd2L1gvbzlsTkY3L1dNVlMydjhYZ1JjQ2hFZUMyL0ZGeHhFZlFZd3lvZVRKN2lwT3BmSWVNKzY4Rmd3SERxWTFMR2RITmQ0MG9nL1VlY2NRTTlEd3RqVDQzdjZUVTNWOFJYL1l0ZWZidDh1dXIzUHF2WndoK2diUXA3c2ZPT1ExTXhYWkR3NW1qRVEyRHpHaVJ6dTdVVTNlUFRtZUFOeldjR0syc1p3RjgzaWdtU1RIM0hpVEhnNmJRY2ZMYldETEpXaTBvLzJQM0xrZitmTHlEWXR3ZGVoMEJoNVh4ODdmZjROODJYMkpQTEgvajV3WUswNmpOYnZSYWROWFRiYk5xTlV6V2VXd3l4S3NTRklBNGxBdUJ0a1hPYVV2dkR6dk1reVJJa1dLaGVNUENNUUc3Z0FjQUFBPQ==\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: db\n  name: db-cm0\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: ' '\n          name: web\n          volumeMounts:\n            - mountPath: /etc/tls\n              name: web-cm0\n            - mountPath: /etc/test-a-key.key\n              name: web-cm1\n              subPath: test-a-key.key\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: web-cm0\n          name: web-cm0\n        - configMap:\n            items:\n              - key: a.key\n                path: test-a-key.key\n            name: web-cm1\n          name: web-cm1\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\ndata:\n  a.crt: test-crt-data...\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web-cm0\n\n---\napiVersion: v1\ndata:\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: web\n  name: web-cm1\n\n"
  },
  {
    "path": "script/test/fixtures/configmap-volume/tls/a.crt",
    "content": "test-crt-data..."
  },
  {
    "path": "script/test/fixtures/configmap-volume/tls/a.key",
    "content": "test-key-data...."
  },
  {
    "path": "script/test/fixtures/controller/compose-controller-label-v3.yaml",
    "content": "services:\n  web:\n    image: wordpress:4\n    environment:\n      - WORDPRESS_DB_PASSWORD=password\n      - WORDPRESS_AUTH_KEY=changeme\n      - WORDPRESS_SECURE_AUTH_KEY=changeme\n      - WORDPRESS_LOGGED_IN_KEY=changeme\n      - WORDPRESS_NONCE_KEY=changeme\n      - WORDPRESS_AUTH_SALT=changeme\n      - WORDPRESS_SECURE_AUTH_SALT=changeme\n      - WORDPRESS_LOGGED_IN_SALT=changeme\n      - WORDPRESS_NONCE_SALT=changeme\n      - WORDPRESS_NONCE_AA=changeme\n    ports:\n      - 80\n    depends_on:\n      - mysql\n    deploy:\n      replicas: 3\n    labels:\n      port: wordpress\n  mysql:\n    image: mysql:5.7\n    environment:\n      - MYSQL_ROOT_PASSWORD=password\n    labels:\n      kompose.controller.type: daemonset"
  },
  {
    "path": "script/test/fixtures/controller/compose-controller-label.yaml",
    "content": "web:\n  image: wordpress:4.5\n  ports:\n    - '80'\n  environment:\n    WORDPRESS_AUTH_KEY: changeme\n    WORDPRESS_SECURE_AUTH_KEY: changeme\n    WORDPRESS_LOGGED_IN_KEY: changeme\n    WORDPRESS_NONCE_KEY: changeme\n    WORDPRESS_AUTH_SALT: changeme\n    WORDPRESS_SECURE_AUTH_SALT: changeme\n    WORDPRESS_LOGGED_IN_SALT: changeme\n    WORDPRESS_NONCE_SALT: changeme\n    WORDPRESS_NONCE_AA: changeme\n  restart: always\n  links:\n    - 'db:mysql'\ndb:\n  image: mysql:5.7\n  environment:\n    MYSQL_ROOT_PASSWORD: password\n  restart: always\n  labels:\n    project.logs: /var/log/mysql\n    kompose.controller.type: daemonset"
  },
  {
    "path": "script/test/fixtures/controller/compose-global.yaml",
    "content": "services:\n  worker:\n    image: dockersamples/examplevotingapp_worker\n    deploy:\n      mode: global"
  },
  {
    "path": "script/test/fixtures/controller/compose.yaml",
    "content": "\nservices:\n\n  redis-master:\n    image: registry.k8s.io/redis:e2e \n    ports:\n      - \"6379\"\n\n  redis-replica:\n    image: registry.k8s.io/redis-slave:v2\n    ports:\n      - \"6379\"\n    environment:\n      - GET_HOSTS_FROM=dns\n\n  frontend:\n    image: registry.k8s.io/guestbook:v3\n    ports:\n      - \"80:80\"\n    environment:\n      - GET_HOSTS_FROM=dns\n    labels:\n      kompose.service.type: LoadBalancer\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-controller-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.controller.type\": \"daemonset\",\n          \"kompose.version\": \"%VERSION%\",\n          \"project.logs\": \"/var/log/mysql\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"name\": \"db\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"MYSQL_ROOT_PASSWORD\",\n                    \"value\": \"password\"\n                  }\n                ],\n                \"image\": \"mysql:5.7\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"db\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"WORDPRESS_AUTH_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_AUTH_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_LOGGED_IN_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_LOGGED_IN_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_AA\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_SECURE_AUTH_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_SECURE_AUTH_SALT\",\n                    \"value\": \"changeme\"\n                  }\n                ],\n                \"image\": \"wordpress:4.5\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-controller-v3-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"port\": \"wordpress\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.controller.type\": \"daemonset\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mysql\"\n        },\n        \"name\": \"mysql\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mysql\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"MYSQL_ROOT_PASSWORD\",\n                    \"value\": \"password\"\n                  }\n                ],\n                \"image\": \"mysql:5.7\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"mysql\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"port\": \"wordpress\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 3,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\",\n              \"port\": \"wordpress\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"WORDPRESS_AUTH_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_AUTH_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_DB_PASSWORD\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_LOGGED_IN_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_LOGGED_IN_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_AA\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_SECURE_AUTH_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_SECURE_AUTH_SALT\",\n                    \"value\": \"changeme\"\n                  }\n                ],\n                \"image\": \"wordpress:4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-daemonset-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"name\": \"frontend\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"frontend\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"name\": \"redis-master\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-master\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"name\": \"redis-replica\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-replica\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-deployment-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"name\": \"frontend\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"frontend\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"LoadBalancer\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"frontend\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"name\": \"redis-master\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-master\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-master\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"name\": \"redis-replica\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-replica\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-replica\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-global-deployment-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"worker\"\n        },\n        \"name\": \"worker\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"worker\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"worker\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"dockersamples/examplevotingapp_worker\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"worker\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-global-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"worker\"\n        },\n        \"name\": \"worker\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"worker\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"dockersamples/examplevotingapp_worker\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"worker\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-k8s-rc-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"ReplicationController\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"frontend\",\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {\n        \"replicas\": 0\n      }\n    },\n    {\n      \"kind\": \"ReplicationController\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-master\",\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {\n        \"replicas\": 0\n      }\n    },\n    {\n      \"kind\": \"ReplicationController\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-replica\",\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {\n        \"replicas\": 0\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/controller/output-os-controller-v3-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"port\": \"wordpress\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.controller.type\": \"daemonset\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mysql\"\n        },\n        \"name\": \"mysql\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mysql\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"MYSQL_ROOT_PASSWORD\",\n                    \"value\": \"password\"\n                  }\n                ],\n                \"image\": \"mysql:5.7\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"mysql\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mysql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mysql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.controller.type\": \"daemonset\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"mysql\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"mysql:5.7\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"mysql\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mysql\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"mysql\",\n                \"image\": \" \",\n                \"env\": [\n                  {\n                    \"name\": \"MYSQL_ROOT_PASSWORD\",\n                    \"value\": \"password\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mysql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mysql\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"5.7\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"mysql:5.7\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"port\": \"wordpress\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:4\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 3,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"WORDPRESS_AUTH_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_AUTH_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_DB_PASSWORD\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_LOGGED_IN_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_LOGGED_IN_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_AA\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_NONCE_SALT\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_SECURE_AUTH_KEY\",\n                    \"value\": \"changeme\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_SECURE_AUTH_SALT\",\n                    \"value\": \"changeme\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"4\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"wordpress:4\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/cronjob/compose.yaml",
    "content": "\nservices:\n  challenge:\n    image: busybox:stable-glibc\n    labels:\n      kompose.cronjob.schedule: \"* * * * *\"\n      kompose.cronjob.concurrency_policy: \"Forbid\"\n      kompose.cronjob.backoff_limit: \"0\"\n    command:\n      - \"bash\"\n      - \"-c\"\n      - \"echo hello from cron\"\n    restart: \"no\"\n"
  },
  {
    "path": "script/test/fixtures/cronjob/output-k8s.yaml",
    "content": "---\napiVersion: batch/v1\nkind: CronJob\nmetadata:\n  labels:\n    io.kompose.service: challenge\n  name: challenge\nspec:\n  concurrencyPolicy: Forbid\n  jobTemplate:\n    spec:\n      backoffLimit: 0\n      template:\n        metadata:\n          labels:\n            io.kompose.service: challenge\n        spec:\n          containers:\n            - args:\n                - bash\n                - -c\n                - echo hello from cron\n              image: busybox:stable-glibc\n              name: challenge\n          restartPolicy: Never\n  schedule: '* * * * *'\n"
  },
  {
    "path": "script/test/fixtures/cronjob/output-os.yaml",
    "content": "---\napiVersion: batch/v1\nkind: CronJob\nmetadata:\n  labels:\n    io.kompose.service: challenge\n  name: challenge\nspec:\n  concurrencyPolicy: Forbid\n  jobTemplate:\n    spec:\n      backoffLimit: 0\n      template:\n        metadata:\n          labels:\n            io.kompose.service: challenge\n        spec:\n          containers:\n            - args:\n                - bash\n                - -c\n                - echo hello from cron\n              image: busybox:stable-glibc\n              name: challenge\n          restartPolicy: Never\n  schedule: '* * * * *'\n"
  },
  {
    "path": "script/test/fixtures/deploy/labels/compose.yaml",
    "content": "services:\n  app:\n    image: node:18-alpine\n    ports:\n      - 3000:3000\n    deploy:\n      labels:\n        kompose.ephemeral-storage.request: 1Gi\n        kompose.ephemeral-storage.limit: 1Gi\n"
  },
  {
    "path": "script/test/fixtures/deploy/labels/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  ports:\n    - name: \"3000\"\n      port: 3000\n      targetPort: 3000\n  selector:\n    io.kompose.service: app\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: app\n    kompose.ephemeral-storage.limit: 1Gi\n    kompose.ephemeral-storage.request: 1Gi\n  name: app\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: app\n  template:\n    metadata:\n      labels:\n        io.kompose.service: app\n    spec:\n      containers:\n        - image: node:18-alpine\n          name: app\n          ports:\n            - containerPort: 3000\n              protocol: TCP\n          resources:\n            limits:\n              ephemeral-storage: 1Gi\n            requests:\n              ephemeral-storage: 1Gi\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/deploy/placement/compose-placement.yaml",
    "content": "services:\n  redis:\n    image: redis\n    ports:\n      - \"6379\"\n    deploy:\n      placement:\n        constraints:\n          - node.hostname == machine\n          - engine.labels.operatingsystem == ubuntu 14.04\n          - node.labels.foo != bar\n          - baz != qux\n        preferences:\n          - spread: node.labels.zone\n          - spread: foo\n          - spread: node.labels.ssd"
  },
  {
    "path": "script/test/fixtures/deploy/placement/output-placement-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      affinity:\n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n              - matchExpressions:\n                  - key: kubernetes.io/hostname\n                    operator: In\n                    values:\n                      - machine\n                  - key: kubernetes.io/os\n                    operator: In\n                    values:\n                      - ubuntu 14.04\n                  - key: foo\n                    operator: NotIn\n                    values:\n                      - bar\n      containers:\n        - image: redis\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n      restartPolicy: Always\n      topologySpreadConstraints:\n        - labelSelector:\n            matchLabels:\n              io.kompose.service: redis\n          maxSkew: 2\n          topologyKey: zone\n          whenUnsatisfiable: ScheduleAnyway\n        - labelSelector:\n            matchLabels:\n              io.kompose.service: redis\n          maxSkew: 1\n          topologyKey: ssd\n          whenUnsatisfiable: ScheduleAnyway\n\n\n"
  },
  {
    "path": "script/test/fixtures/deploy/placement/output-placement-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      affinity:\n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n              - matchExpressions:\n                  - key: kubernetes.io/hostname\n                    operator: In\n                    values:\n                      - machine\n                  - key: kubernetes.io/os\n                    operator: In\n                    values:\n                      - ubuntu 14.04\n                  - key: foo\n                    operator: NotIn\n                    values:\n                      - bar\n      containers:\n        - image: ' '\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n      restartPolicy: Always\n      topologySpreadConstraints:\n        - labelSelector:\n            matchLabels:\n              io.kompose.service: redis\n          maxSkew: 2\n          topologyKey: zone\n          whenUnsatisfiable: ScheduleAnyway\n        - labelSelector:\n            matchLabels:\n              io.kompose.service: redis\n          maxSkew: 1\n          topologyKey: ssd\n          whenUnsatisfiable: ScheduleAnyway\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/dockerfilepath/compose.yaml",
    "content": "\nservices:\n foo:\n  build:\n   context: \"../../script/test_in_openshift/buildconfig\"\n   dockerfile: \"/Dockerfile\"\n  command: \"sleep 120\"\n"
  },
  {
    "path": "script/test/fixtures/domain/compose-v3.yaml",
    "content": "services:\n  dns:\n    image: phensley/docker-dns\n    hostname: affy\n    domainname: affy.com\n"
  },
  {
    "path": "script/test/fixtures/domain/compose.yaml",
    "content": "services:\n  dns:\n    image: phensley/docker-dns\n    hostname: affy\n    domainname: affy.com\n"
  },
  {
    "path": "script/test/fixtures/domain/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"dns\"\n        },\n        \"name\": \"dns\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"dns\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"dns\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"phensley/docker-dns\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"dns\",\n                \"resources\": {}\n              }\n            ],\n            \"hostname\": \"affy\",\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"subdomain\": \"affy.com\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/domain/output-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"dns\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"dns\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"dns\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"dns:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"dns\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"dns\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"dns\",\n                \"image\": \" \",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"hostname\": \"affy\",\n            \"subdomain\": \"affy.com\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"dns\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"dns\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"phensley/docker-dns\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/entrypoint-command/compose.yaml",
    "content": "\nservices:\n  base:\n    image: busybox\n    entrypoint: echo\n    command: foo\n    labels:\n      kompose.service.type: headless\n"
  },
  {
    "path": "script/test/fixtures/entrypoint-command/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"base\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"name\": \"base\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"base\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"base\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"args\": [\n                  \"foo\"\n                ],\n                \"command\": [\n                  \"echo\"\n                ],\n                \"image\": \"busybox\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"base\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/entrypoint-command/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"base\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"base\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"base\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"base:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"base\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"base\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"base\",\n                \"image\": \" \",\n                \"command\": [\n                  \"echo\"\n                ],\n                \"args\": [\n                  \"foo\"\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"base\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"base\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"busybox\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/env/compose.yaml",
    "content": "services:\n  namenode:\n    image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n    environment:\n      - CLUSTER_NAME=test\n    env_file:\n      - hadoop-hive-namenode.env\n    ports:\n      - \"50070:50070\"\n      - \"8020:8020\"\n  another-namenode:\n    image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n    ports:\n      - \"50070:50070\"\n      - \"8020:8020\"\n    env_file:\n      - hadoop-hive-namenode.env\n"
  },
  {
    "path": "script/test/fixtures/env/hadoop-hive-namenode.env",
    "content": "FOO=BAR\nBAR=FOO"
  },
  {
    "path": "script/test/fixtures/env/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: another-namenode\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: namenode\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: another-namenode\n  template:\n    metadata:\n      labels:\n        io.kompose.service: another-namenode\n    spec:\n      containers:\n        - envFrom:\n            - configMapRef:\n                name: hadoop-hive-namenode-env\n          image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n          name: another-namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: v1\ndata:\n  BAR: FOO\n  FOO: BAR\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: another-namenode-hadoop-hive-namenode-env\n  name: hadoop-hive-namenode-env\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: namenode\n  template:\n    metadata:\n      labels:\n        io.kompose.service: namenode\n    spec:\n      containers:\n        - env:\n            - name: CLUSTER_NAME\n              value: test\n          envFrom:\n            - configMapRef:\n                name: hadoop-hive-namenode-env\n          image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n          name: namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/env/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: another-namenode\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: namenode\n\n---\napiVersion: v1\ndata:\n  BAR: FOO\n  FOO: BAR\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: another-namenode-hadoop-hive-namenode-env\n  name: hadoop-hive-namenode-env\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: another-namenode\n  template:\n    metadata:\n      labels:\n        io.kompose.service: another-namenode\n    spec:\n      containers:\n        - envFrom:\n            - configMapRef:\n                name: hadoop-hive-namenode-env\n          image: ' '\n          name: another-namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - another-namenode\n        from:\n          kind: ImageStreamTag\n          name: another-namenode:2.0.0-hadoop2.7.4-java8\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n      name: 2.0.0-hadoop2.7.4-java8\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: namenode\n  template:\n    metadata:\n      labels:\n        io.kompose.service: namenode\n    spec:\n      containers:\n        - env:\n            - name: CLUSTER_NAME\n              value: test\n          envFrom:\n            - configMapRef:\n                name: hadoop-hive-namenode-env\n          image: ' '\n          name: namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - namenode\n        from:\n          kind: ImageStreamTag\n          name: namenode:2.0.0-hadoop2.7.4-java8\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n      name: 2.0.0-hadoop2.7.4-java8\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/env-dotenv/compose.yaml",
    "content": "services:\n  minio:\n    image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z\n    env_file: .env\n    environment:\n      - MINIO_ROOT_USER=${MINIO_USER}\n      - MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}\n      - TZ=${TIMEZONE}\n    ports:\n      - ${MINIO_PORT}:9000\n      - ${MINIO_CONSOLE_PORT}:9001"
  },
  {
    "path": "script/test/fixtures/env-dotenv/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  ports:\n    - name: \"9000\"\n      port: 9000\n      targetPort: 9000\n    - name: \"9001\"\n      port: 9001\n      targetPort: 9001\n  selector:\n    io.kompose.service: minio\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: minio\n  template:\n    metadata:\n      labels:\n        io.kompose.service: minio\n    spec:\n      containers:\n        - env:\n            - name: MINIO_ROOT_PASSWORD\n              value: infini_rag_flow\n            - name: MINIO_ROOT_USER\n              value: rag_flow\n            - name: TZ\n              value: Asia/Shanghai\n          envFrom:\n            - configMapRef:\n                name: env\n          image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z\n          name: minio\n          ports:\n            - containerPort: 9000\n              protocol: TCP\n            - containerPort: 9001\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: v1\ndata:\n  MINIO_CONSOLE_PORT: \"9001\"\n  MINIO_PASSWORD: infini_rag_flow\n  MINIO_PORT: \"9000\"\n  MINIO_USER: rag_flow\n  TIMEZONE: Asia/Shanghai\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: minio-env\n  name: env"
  },
  {
    "path": "script/test/fixtures/env-dotenv/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  ports:\n    - name: \"9000\"\n      port: 9000\n      targetPort: 9000\n    - name: \"9001\"\n      port: 9001\n      targetPort: 9001\n  selector:\n    io.kompose.service: minio\n\n---\napiVersion: v1\ndata:\n  MINIO_CONSOLE_PORT: \"9001\"\n  MINIO_PASSWORD: infini_rag_flow\n  MINIO_PORT: \"9000\"\n  MINIO_USER: rag_flow\n  TIMEZONE: Asia/Shanghai\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: minio-env\n  name: env\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: minio\n  template:\n    metadata:\n      labels:\n        io.kompose.service: minio\n    spec:\n      containers:\n        - env:\n            - name: MINIO_ROOT_PASSWORD\n              value: infini_rag_flow\n            - name: MINIO_ROOT_USER\n              value: rag_flow\n            - name: TZ\n              value: Asia/Shanghai\n          envFrom:\n            - configMapRef:\n                name: env\n          image: ' '\n          name: minio\n          ports:\n            - containerPort: 9000\n              protocol: TCP\n            - containerPort: 9001\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - minio\n        from:\n          kind: ImageStreamTag\n          name: minio:RELEASE.2023-12-20T01-00-02Z\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z\n      name: RELEASE.2023-12-20T01-00-02Z\n      referencePolicy:\n        type: \"\""
  },
  {
    "path": "script/test/fixtures/env-multiple/compose.yaml",
    "content": "services:\n  namenode:\n    image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n    environment:\n      - CLUSTER_NAME=test\n    env_file:\n      - env1/hadoop-hive-namenode.env\n    ports:\n      - \"50070:50070\"\n      - \"8020:8020\"\n  another-namenode:\n    image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n    ports:\n      - \"50070:50070\"\n      - \"8020:8020\"\n    env_file:\n      - env2/hadoop-hive-namenode.env\n"
  },
  {
    "path": "script/test/fixtures/env-multiple/env1/hadoop-hive-namenode.env",
    "content": "FOO=BAR\n"
  },
  {
    "path": "script/test/fixtures/env-multiple/env2/hadoop-hive-namenode.env",
    "content": "BAR=FOO\n"
  },
  {
    "path": "script/test/fixtures/env-multiple/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: another-namenode\n\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: namenode\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: another-namenode\n  strategy: {}\n  template:\n    metadata:\n      creationTimestamp: null\n      labels:\n        io.kompose.service: another-namenode\n    spec:\n      containers:\n        - env:\n            - name: BAR\n              valueFrom:\n                configMapKeyRef:\n                  key: BAR\n                  name: hadoop-hive-namenode-env\n          image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n          name: another-namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n          resources: {}\n      restartPolicy: Always\n\n\n---\napiVersion: v1\ndata:\n  FOO: BAR\nkind: ConfigMap\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: hadoop-hive-namenode-env\n  name: hadoop-hive-namenode-env\n\n---\napiVersion: v1\ndata:\n  BAR: FOO\nkind: ConfigMap\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode-hadoop-hive-namenode-env\n  name: hadoop-hive-namenode-env1\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: namenode\n  strategy: {}\n  template:\n    metadata:\n      creationTimestamp: null\n      labels:\n        io.kompose.service: namenode\n    spec:\n      containers:\n        - env:\n            - name: CLUSTER_NAME\n              value: test\n            - name: FOO\n              valueFrom:\n                configMapKeyRef:\n                  key: FOO\n                  name: hadoop-hive-namenode-env\n          image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n          name: namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n          resources: {}\n      restartPolicy: Always\n\n\n"
  },
  {
    "path": "script/test/fixtures/env-multiple/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: another-namenode\n\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  ports:\n    - name: \"50070\"\n      port: 50070\n      targetPort: 50070\n    - name: \"8020\"\n      port: 8020\n      targetPort: 8020\n  selector:\n    io.kompose.service: namenode\n\n\n---\napiVersion: v1\ndata:\n  FOO: BAR\nkind: ConfigMap\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: hadoop-hive-namenode-env\n  name: hadoop-hive-namenode-env\n\n---\napiVersion: v1\ndata:\n  BAR: FOO\nkind: ConfigMap\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode-hadoop-hive-namenode-env\n  name: hadoop-hive-namenode-env1\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: another-namenode\n  strategy:\n    resources: {}\n  template:\n    metadata:\n      creationTimestamp: null\n      labels:\n        io.kompose.service: another-namenode\n    spec:\n      containers:\n        - env:\n            - name: BAR\n              valueFrom:\n                configMapKeyRef:\n                  key: BAR\n                  name: hadoop-hive-namenode-env1\n          image: ' '\n          name: another-namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n          resources: {}\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - another-namenode\n        from:\n          kind: ImageStreamTag\n          name: another-namenode:2.0.0-hadoop2.7.4-java8\n      type: ImageChange\n\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: another-namenode\n  name: another-namenode\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - annotations: null\n      from:\n        kind: DockerImage\n        name: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n      generation: null\n      importPolicy: {}\n      name: 2.0.0-hadoop2.7.4-java8\n      referencePolicy:\n        type: \"\"\n\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: namenode\n  strategy:\n    resources: {}\n  template:\n    metadata:\n      creationTimestamp: null\n      labels:\n        io.kompose.service: namenode\n    spec:\n      containers:\n        - env:\n            - name: CLUSTER_NAME\n              value: test\n            - name: FOO\n              valueFrom:\n                configMapKeyRef:\n                  key: FOO\n                  name: hadoop-hive-namenode-env\n          image: ' '\n          name: namenode\n          ports:\n            - containerPort: 50070\n              protocol: TCP\n            - containerPort: 8020\n              protocol: TCP\n          resources: {}\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - namenode\n        from:\n          kind: ImageStreamTag\n          name: namenode:2.0.0-hadoop2.7.4-java8\n      type: ImageChange\n\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  creationTimestamp: null\n  labels:\n    io.kompose.service: namenode\n  name: namenode\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - annotations: null\n      from:\n        kind: DockerImage\n        name: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8\n      generation: null\n      importPolicy: {}\n      name: 2.0.0-hadoop2.7.4-java8\n      referencePolicy:\n        type: \"\"\n\n\n"
  },
  {
    "path": "script/test/fixtures/envfile-interpolation/compose.yaml",
    "content": "\nservices:\n  minio:\n    image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z\n    container_name: ragflow-minio\n    command: server --console-address \":9001\" /data\n    ports:\n      - ${MINIO_PORT}:9000\n      - ${MINIO_CONSOLE_PORT}:9001\n    env_file: .env\n    environment:\n      - DOC_ENGINE=test-env\n    restart: on-failure\n"
  },
  {
    "path": "script/test/fixtures/envfile-interpolation/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  ports:\n    - name: \"9000\"\n      port: 9000\n      targetPort: 9000\n    - name: \"9001\"\n      port: 9001\n      targetPort: 9001\n  selector:\n    io.kompose.service: minio\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  containers:\n    - args:\n        - server\n        - --console-address\n        - :9001\n        - /data\n      envFrom:\n        - configMapRef:\n            name: env\n      image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z\n      name: ragflow-minio\n      ports:\n        - containerPort: 9000\n          protocol: TCP\n        - containerPort: 9001\n          protocol: TCP\n  restartPolicy: OnFailure\n\n---\napiVersion: v1\ndata:\n  COMPOSE_PROFILES: test-env\n  DOC_ENGINE: test-env\n  MINIO_CONSOLE_PORT: \"9001\"\n  MINIO_PORT: \"9000\"\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: minio-env\n  name: env"
  },
  {
    "path": "script/test/fixtures/envfile-interpolation/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  ports:\n    - name: \"9000\"\n      port: 9000\n      targetPort: 9000\n    - name: \"9001\"\n      port: 9001\n      targetPort: 9001\n  selector:\n    io.kompose.service: minio\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    io.kompose.service: minio\n  name: minio\nspec:\n  containers:\n    - args:\n        - server\n        - --console-address\n        - :9001\n        - /data\n      envFrom:\n        - configMapRef:\n            name: env\n      image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z\n      name: ragflow-minio\n      ports:\n        - containerPort: 9000\n          protocol: TCP\n        - containerPort: 9001\n          protocol: TCP\n  restartPolicy: OnFailure\n\n---\napiVersion: v1\ndata:\n  COMPOSE_PROFILES: test-env\n  DOC_ENGINE: test-env\n  MINIO_CONSOLE_PORT: \"9001\"\n  MINIO_PORT: \"9000\"\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: minio-env\n  name: env"
  },
  {
    "path": "script/test/fixtures/envvars-interpolation/compose.yaml",
    "content": "\nservices:\n    myservice:\n        image: alpine\n        environment:\n            PROTOCOL: 'https'\n            DOMAIN: 'google.com'\n        command:\n            [\n                'curl',\n                '$PROTOCOL://$DOMAIN/',\n            ]\n"
  },
  {
    "path": "script/test/fixtures/envvars-interpolation/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: myservice\n  name: myservice\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: myservice\n  template:\n    metadata:\n      labels:\n        io.kompose.service: myservice\n    spec:\n      containers:\n        - args:\n            - curl\n            - :///\n          env:\n            - name: DOMAIN\n              value: google.com\n            - name: PROTOCOL\n              value: https\n          image: alpine\n          name: myservice\n      restartPolicy: Always\n\n\n"
  },
  {
    "path": "script/test/fixtures/envvars-interpolation/output-os.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: myservice\n  name: myservice\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: myservice\n  template:\n    metadata:\n      labels:\n        io.kompose.service: myservice\n    spec:\n      containers:\n        - args:\n            - curl\n            - :///\n          env:\n            - name: DOMAIN\n              value: google.com\n            - name: PROTOCOL\n              value: https\n          image: ' '\n          name: myservice\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - myservice\n        from:\n          kind: ImageStreamTag\n          name: myservice:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: myservice\n  name: myservice\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: alpine\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/envvars-separators/compose.yaml",
    "content": "mongodb:\n  image: mongo:latest\n  container_name: mongodb\n  command: mongod --smallfiles\n  ports:\n   - \"27017:27017\"\n  volumes:\n   - ./mongo:/data/db:rw\n  volume_driver: local\nhygieia-api:\n  image: hygieia-api:latest\n  container_name: hygieia-api\n  ports:\n  - \"8080:8080\"\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\nhygieia-ui:\n  image: hygieia-ui:latest\n  container_name: hygieia-ui\n  ports:\n  - \"8088:80\"\n  links:\n  - hygieia-api\n\n\nhygieia-github-scm-collector:\n  image: hygieia-github-scm-collector:latest\n  container_name: hygieia-github\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n# place any values you want to change in docker-compose.override.yml\n#  environment:\n#  - GITHUB_HOST=github.com\n#  - GITHUB_CRON='0 0/5 * * * *'\n#  - GITHUB_COMMIT_THREASHOLD_DAYS=15\n\n\n\nhygieia-jira-feature-collector:\n  image: hygieia-jira-feature-collector:latest\n  container_name: hygieia-jira\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n  environment:\n        # you can override these by creating a docker-compose.overider.yml and put in entries like this:\n        #REQUIRED Entries\n  - JIRA_BASE_URL=https://jira.atlassian.com\n        #64-bit encoded credentials with the pattern username:password\n        #on a mac you con create them with : echo \"username:password\" | base64\n        #reference:  https://www.base64decode.org/\n  - JIRA_CREDENTIALS=username:password\n\n        #OPTIONAL - you may want ot tweek these\n#  - JIRA_CRON=\"0 * * * * *\"\n        #Start dates from which to begin collector data, if no other data is present - usually, a month back is appropriate (required)\n#  - JIRA_DELTA_START_DATE=2015-03-01T00:00:00.000000\n#  - JIRA_MASTER_START_DATE=2008-01-01T00:00:00.000000\n\n        #OPTIONAL Overrides if you need them\n        #Page size for data calls (Jira maxes at 1000)\n#  - JIRA_PAGE_SIZE=1000\n        #Jira Connection Details\n#  - JIRA_PROXY_URL=\n#  - JIRA_PROXY_PORT=\n        # Trending Query:  Number of days in a sprint (not-required)\n#  - JIRA_SPRINT_DAYS=60\n        # Trending Query:  Length of sprint week (not-required)\n#  - JIRA_SPRINT_END_PRIOR=7\n        #Scheduled Job prior minutes to recover data created during execution time (usually, 2 minutes is enough)\n#  - JIRA_SCHEDULED_PRIOR_MIN=2\n        #Delta change date that modulates the collector item task - should be about as far back as possible, in ISO format (required)\n#  - JIRA_DELTA_COLLECTOR_ITEM_START_DATE=2008-01-01T00:00:00.000000\n        #Jira Connection Details\n#  - JIRA_QUERY_ENDPOINT=rest/api/2/\n        #OAuth2.0 token credentials (currently not supported in this version)\n#  - JIRA_OAUTH_AUTH_TOKEN=sdfghjkl==\n#  - JIRA_OAUTH_REFRESH_TOKEN=sdfagheh==\n#  - JIRA_OAUTH_REDIRECT_URL=uri.this.is.test:uri\n#  - JIRA_OAUTH_EXPIRE_TIME=234567890987\n\n# In Jira, general IssueType IDs are associated to various \"issue\"\n# attributes. However, there is one attribute which this collector's\n# queries rely on that change between different instantiations of Jira.\n# Please provide a numerical ID reference to your instance's IssueType for\n# the lowest level of Issues (e.g., \"user story\") specific to your Jira\n# instance.  Note:  You can retrieve your instance's IssueType ID\n# listings via the following URI:  https://[your-jira-domain-name]/rest/api/2/issuetype/\n#  - JIRA_ISSUE_TYPE_ID=Story\n\n# In Jira, your instance will have its own custom field created for \"sprint\" or \"timebox\" details,\n# which includes a list of information.  This field allows you to specify that data field for your\n# instance of Jira. Note: You can retrieve your instance's sprint data field name\n# via the following URI, and look for a package name com.atlassian.greenhopper.service.sprint.Sprint;\n# your custom field name describes the values in this field:\n# https://[your-jira-domain-name]/rest/api/2/issue/[some-issue-name]\n#  - JIRA_SPRINT_DATA_FIELD_NAME=customfield_10007\n\n# In Jira, your instance will have its own custom field created for \"super story\" or \"epic\" back-end ID,\n# which includes a list of information.  This field allows you to specify that data field for your instance\n# of Jira.  Note:  You can retrieve your instance's epic ID field name via the following URI where your\n# queried user story issue has a super issue (e.g., epic) tied to it; your custom field name describes the\n# epic value you expect to see, and is the only field that does this for a given issue:\n# https://[your-jira-domain-name]/rest/api/2/issue/[some-issue-name]\n#  - JIRA_EPIC_FIELD_NAME=customfield_10400\n\n# In Jira, your instance will have its own custom field created for \"story points\"\n# This field allows you to specify that data field for your instance\n# of Jira.  Note:  You can retrieve your instance's storypoints ID field name via the following URI where your\n# queried user story issue has story points set on it; your custom field name describes the\n# story points value you expect to see:\n# https://[your-jira-domain-name]/rest/api/2/issue/[some-issue-name]\n#  - JIRA_STORY_POINTS_FIELD_NAME=customfield_10002\n\nhygieia-jenkins-build-collector:\n  image: hygieia-jenkins-build-collector:latest\n  container_name: hygieia-jenkins-build\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n#Jenkins server (required) - Can provide multiple\n#  - JENKINS_MASTER=ttp://jenkins.company.com\n#If using username/token for api authentication (required for Cloudbees Jenkins Ops Center) see sample\n#  - JENKINS_OP_CENTER=http://username:token@jenkins.company.com\n#Another option: If using same username/password Jenkins auth - set username/apiKey to use HTTP Basic Auth (blank=no auth)\n#  - JENKINS_USERNAME\n#  - JENKINS_API_KEY\n#  - JENKINS_CRON=0 0/5 * * * *\n#Determines if build console log is collected - defaults to false\n#  - JENKINS_SAVE_LOG=true\n\nhygieia-jenkins-cucumber-test-collector:\n  image: hygieia-jenkins-cucumber-test-collector:latest\n  container_name: hygieia-jenkins-cucumber\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n#Jenkins server (required) - Can provide multiple\n#  - JENKINS_MASTER=ttp://jenkins.company.com\n#If using username/token for api authentication (required for Cloudbees Jenkins Ops Center) see sample\n#  - JENKINS_OP_CENTER=http://username:token@jenkins.company.com\n#Another option: If using same username/password Jenkins auth - set username/apiKey to use HTTP Basic Auth (blank=no auth)\n#  - JENKINS_USERNAME\n#  - JENKINS_API_KEY\n#  - JENKINS_CRON=0 0/5 * * * *\n#Determines if build console log is collected - defaults to false\n#  - JENKINS_SAVE_LOG=true\n\nhygieia-sonar-codequality-collector:\n  image: hygieia-sonar-codequality-collector:latest\n  container_name: hygieia-sonar-codequality\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n#  - SONAR_CRON=0 0/5 * * * *\n#  - SONAR_URL=http://localhost:9000\n\nhygieia-chat-ops-collector:\n  image: hygieia-chat-ops-collector:latest\n  container_name: hygieia-chat-ops\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n#  - CHATOPS_CRON=0 0/5 * * * *\n\nhygieia-subversion-scm-collector:\n  image: hygieia-subversion-scm-collector:latest\n  container_name: hygieia-subversion\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n#  - SUBVERSION_CRON:-0 0/5 * * * *\n\n#Shared subversion username and password\n#  - SUBVERSION_USERNAME=\n#  - SUBVERSION_PASSWORD=\n\n#Maximum number of days to go back in time when fetching commits\n#  - SUBVERSION_COMMIT_THRESHOLD_DAYS=15\n\nhygieia-bitbucket-scm-collector:\n  image: hygieia-bitbucket-scm-collector:latest\n  container_name: hygieia-bitbucket\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n    #mandatory\n#  - BITBUCKET_HOST=mybitbucketrepo.com/\n#  - BITBUCKET_API=/rest/api/1.0/\n#  - BITBUCKET_CRON=0 0/5 * * * *\n#  - BITBUCKET_PRODUCT=cloud\n\n#Maximum number of days to go back in time when fetching commits. Only applicable to Bitbucket Cloud.\n#  - BITBUCKET_COMMIT_THRESHOLD_DAYS=15\n\n#Page size for rest calls. Only applicable to Bitbucket Server.\n#  - BITBUCKET_PAGE_SIZE=25\n\nhygieia-versionone-collector:\n  image: hygieia-versionone-collector:latest\n  container_name: hygieia-versionone\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n#  environment:\n#Page size for data calls (VersionOne recommended 2000)\n#  - VERSIONONE_PAGE_SIZE=2000\n\n#In-built folder housing prepared REST queries (required)\n#  - VERSIONONE_QUERY_FOLDER=v1api-queries\n\n#Jira API Query file names (String template requires the files to have .st extension) (required)\n#  - VERSIONONE_STORY_QUERY=story\n#  - VERSIONONE_EPIC_QUERY=epicinfo\n#  - VERSIONONE_PROJECT_QUERY=projectinfo\n#  - VERSIONONE_MEMBBER_QUERY=memberinfo\n#  - VERSIONONE_SPRINT_QUERY=sprintinfo\n#  - VERSIONONE_TEAM_QUERY=teaminfo\n#  - VERSIONONE_TRENDING_QUERY=trendinginfo\n\n# Trending Query:  Number of days in a sprint (not-required)\n#  - VERSIONONE_SPRINT_DAYS=60\n# Trending Query:  Length of sprint week (not-required)\n#  - VERSIONONE_SPRINT_END_PRIOR=7\n\n#Scheduled Job prior minutes to recover data created during execution time (usually, 2 minutes is enough)\n#  - VERSIONONE_SCHEDULED_PRIOR_MIN=2\n\n#Delta change date that modulates the collector item task - should be about as far back as possible, in ISO format (required)\n#  - VERSIONONE_DELTA_COLLECTORITEM_START_DATE=2008-01-01T00:00:00.000000\n\n#VersionOne Connection Details\n#Proxy assumes a host:port syntax\n#  - VERSIONONE_PROXY_URL=\"\"\n#  - VERSIONONE_URL=https://www.versionone.com/our-company-instance/\n#Access token provided by VersionOne\n#  - VERSIONONE_ACCESS_TOKEN=accessToken\n\n#Start dates from which to begin collector data, if no other data is present - usually, a month back is appropriate (required)\n#  - VERSIONONE_DELTA_START_DATE=2015-03-01T00:00:00.000000\n#  - VERSIONONE_MASTER_START_DATE=2008-01-01T00:00:00.000000\n\nhygieia-udeploy-collector:\n  image: hygieia-udeploy-collector:latest\n  container_name: hygieia-udeploy\n  volumes:\n  - ./logs:/hygieia/logs\n  links:\n  - mongodb:mongo\n  - hygieia-api\n  environment:\n#UDeploy server (required) - Can provide multiple\n  - UDEPLOY_URL:-http://udeploy.company.com\n#UDeploy user name (required)\n  - UDEPLOY_USERNAME:-bobama\n#UDeploy password (required)\n  - UDEPLOY_PASSWORD:-s3cr3t\n#Collector schedule (required)\n#  - UDEPLOY_CRON:-0 0/5 * * * *\n"
  },
  {
    "path": "script/test/fixtures/envvars-separators/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-api\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-api\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"hygieia-api\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-ui\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-ui\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8088\",\n            \"port\": 8088,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"hygieia-ui\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mongodb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mongodb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"27017\",\n            \"port\": 27017,\n            \"targetPort\": 27017\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mongodb\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-api\"\n        },\n        \"name\": \"hygieia-api\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-api\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-api\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-api:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-api\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-api-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-api-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-api-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-api-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-api-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-bitbucket-scm-collector\"\n        },\n        \"name\": \"hygieia-bitbucket-scm-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-bitbucket-scm-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-bitbucket-scm-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-bitbucket-scm-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-bitbucket\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-bitbucket-scm-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-bitbucket-scm-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-bitbucket-scm-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-bitbucket-scm-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-bitbucket-scm-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-chat-ops-collector\"\n        },\n        \"name\": \"hygieia-chat-ops-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-chat-ops-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-chat-ops-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-chat-ops-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-chat-ops\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-chat-ops-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-chat-ops-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-chat-ops-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-chat-ops-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-chat-ops-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-github-scm-collector\"\n        },\n        \"name\": \"hygieia-github-scm-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-github-scm-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-github-scm-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-github-scm-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-github\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-github-scm-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-github-scm-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-github-scm-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-github-scm-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-github-scm-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-jenkins-build-collector\"\n        },\n        \"name\": \"hygieia-jenkins-build-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-jenkins-build-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-jenkins-build-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-jenkins-build-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-jenkins-build\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-jenkins-build-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-jenkins-build-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-jenkins-build-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-jenkins-build-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-jenkins-build-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-jenkins-cucumber-test-collector\"\n        },\n        \"name\": \"hygieia-jenkins-cucumber-test-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-jenkins-cucumber-test-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-jenkins-cucumber-test-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-jenkins-cucumber-test-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-jenkins-cucumber\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-jenkins-cucumber-test-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-jenkins-cucumber-test-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-jenkins-cucumber-test-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-jenkins-cucumber-test-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-jenkins-cucumber-test-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-jira-feature-collector\"\n        },\n        \"name\": \"hygieia-jira-feature-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-jira-feature-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-jira-feature-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"JIRA_BASE_URL\",\n                    \"value\": \"https://jira.atlassian.com\"\n                  },\n                  {\n                    \"name\": \"JIRA_CREDENTIALS\",\n                    \"value\": \"username:password\"\n                  }\n                ],\n                \"image\": \"hygieia-jira-feature-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-jira\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-jira-feature-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-jira-feature-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-jira-feature-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-jira-feature-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-jira-feature-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-sonar-codequality-collector\"\n        },\n        \"name\": \"hygieia-sonar-codequality-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-sonar-codequality-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-sonar-codequality-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-sonar-codequality-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-sonar-codequality\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-sonar-codequality-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-sonar-codequality-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-sonar-codequality-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-sonar-codequality-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-sonar-codequality-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-subversion-scm-collector\"\n        },\n        \"name\": \"hygieia-subversion-scm-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-subversion-scm-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-subversion-scm-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-subversion-scm-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-subversion\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-subversion-scm-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-subversion-scm-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-subversion-scm-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-subversion-scm-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-subversion-scm-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-udeploy-collector\"\n        },\n        \"name\": \"hygieia-udeploy-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-udeploy-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-udeploy-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"UDEPLOY_PASSWORD\",\n                    \"value\": \"-s3cr3t\"\n                  },\n                  {\n                    \"name\": \"UDEPLOY_URL\",\n                    \"value\": \"-http://udeploy.company.com\"\n                  },\n                  {\n                    \"name\": \"UDEPLOY_USERNAME\",\n                    \"value\": \"-bobama\"\n                  }\n                ],\n                \"image\": \"hygieia-udeploy-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-udeploy\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-udeploy-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-udeploy-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-udeploy-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-udeploy-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-udeploy-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-ui\"\n        },\n        \"name\": \"hygieia-ui\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-ui\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-ui\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-ui:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-ui\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-versionone-collector\"\n        },\n        \"name\": \"hygieia-versionone-collector\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"hygieia-versionone-collector\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"hygieia-versionone-collector\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"hygieia-versionone-collector:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"hygieia-versionone\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/hygieia/logs\",\n                    \"name\": \"hygieia-versionone-collector-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"hygieia-versionone-collector-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"hygieia-versionone-collector-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"hygieia-versionone-collector-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"hygieia-versionone-collector-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mongodb\"\n        },\n        \"name\": \"mongodb\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"mongodb\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mongodb\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"args\": [\n                  \"mongod\",\n                  \"--smallfiles\"\n                ],\n                \"image\": \"mongo:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"mongodb\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 27017\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/data/db\",\n                    \"name\": \"mongodb-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"mongodb-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"mongodb-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mongodb-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mongodb-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/envvars-with-status/compose.yaml",
    "content": "services:\n  app:\n    image: node:18-alpine\n    command: sh -c \"yarn install && yarn run dev\"\n    ports:\n      - 3000:3000\n    environment:\n      TOPICS: foo:1,status:2,bar:3\n      OTHER_ENV: example\n"
  },
  {
    "path": "script/test/fixtures/envvars-with-status/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  ports:\n    - name: \"3000\"\n      port: 3000\n      targetPort: 3000\n  selector:\n    io.kompose.service: app\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: app\n  template:\n    metadata:\n      labels:\n        io.kompose.service: app\n    spec:\n      containers:\n        - args:\n            - sh\n            - -c\n            - yarn install && yarn run dev\n          env:\n            - name: OTHER_ENV\n              value: example\n            - name: TOPICS\n              value: foo:1,status:2,bar:3\n          image: node:18-alpine\n          name: app\n          ports:\n            - containerPort: 3000\n              protocol: TCP\n      restartPolicy: Always\n"
  },
  {
    "path": "script/test/fixtures/envvars-with-status/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  ports:\n    - name: \"3000\"\n      port: 3000\n      targetPort: 3000\n  selector:\n    io.kompose.service: app\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: app\n  template:\n    metadata:\n      labels:\n        io.kompose.service: app\n    spec:\n      containers:\n        - args:\n            - sh\n            - -c\n            - yarn install && yarn run dev\n          env:\n            - name: OTHER_ENV\n              value: example\n            - name: TOPICS\n              value: foo:1,status:2,bar:3\n          image: ' '\n          name: app\n          ports:\n            - containerPort: 3000\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - app\n        from:\n          kind: ImageStreamTag\n          name: app:18-alpine\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: node:18-alpine\n      name: 18-alpine\n      referencePolicy:\n        type: \"\"\n"
  },
  {
    "path": "script/test/fixtures/etherpad/README.md",
    "content": "## Compose Etherpad\n\nEtherpad and Mariadb\n\n### Usage\n\nThe simplest thing to do:\n\n```bash\nexport $(cat envs)\ndocker-compose up\n```\n\nTo customize the values edit `envs` file.\n"
  },
  {
    "path": "script/test/fixtures/etherpad/docker-compose-no-image.yml",
    "content": "\nservices:\n  mariadb:\n    ports:\n      - 3306\n\n  etherpad:\n    ports:\n      - \"80:9001\"\n\n"
  },
  {
    "path": "script/test/fixtures/etherpad/docker-compose-no-ports.yml",
    "content": "\nservices:\n  mariadb:\n    image: centos/mariadb\n"
  },
  {
    "path": "script/test/fixtures/etherpad/docker-compose.yml",
    "content": "\nservices:\n  mariadb:\n    image: centos/mariadb\n    ports:\n      - \"$DB_PORT\"\n    environment:\n      MYSQL_ROOT_PASSWORD: $ROOT_PASS\n      MYSQL_DATABASE: $DB_NAME\n      MYSQL_PASSWORD: $DB_PASS\n      MYSQL_USER: $DB_USER\n    volumes:\n      - /var/lib/mysql\n\n  etherpad:\n    image: centos/etherpad\n    ports:\n      - \"80:9001\"\n    depends_on:\n      - mariadb\n    environment:\n      DB_HOST: $DB_HOST\n      DB_DBID: $DB_NAME\n      DB_PASS: $DB_PASS\n      DB_PORT: $DB_PORT\n      DB_USER: $DB_USER\n"
  },
  {
    "path": "script/test/fixtures/etherpad/envs",
    "content": "DB_HOST=mariadb\nROOT_PASS=etherpad\nDB_NAME=etherpad\nDB_PASS=etherpad\nDB_USER=etherpad\nDB_PORT=3306\n"
  },
  {
    "path": "script/test/fixtures/etherpad/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"etherpad\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"etherpad\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 9001\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"etherpad\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3306\",\n            \"port\": 3306,\n            \"targetPort\": 3306\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"etherpad\"\n        },\n        \"name\": \"etherpad\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"etherpad\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"etherpad\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"DB_DBID\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"DB_HOST\",\n                    \"value\": \"mariadb\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"DB_PORT\",\n                    \"value\": \"3306\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"etherpad\"\n                  }\n                ],\n                \"image\": \"centos/etherpad\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"etherpad\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 9001\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"name\": \"mariadb\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"mariadb\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mariadb\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"MYSQL_DATABASE\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"MYSQL_PASSWORD\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"MYSQL_ROOT_PASSWORD\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"MYSQL_USER\",\n                    \"value\": \"etherpad\"\n                  }\n                ],\n                \"image\": \"centos/mariadb\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"mariadb\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3306\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/lib/mysql\",\n                    \"name\": \"mariadb-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"mariadb-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"mariadb-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/etherpad/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"etherpad\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"etherpad\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 9001\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"etherpad\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3306\",\n            \"port\": 3306,\n            \"targetPort\": 3306\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"etherpad\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"etherpad\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"etherpad\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"etherpad:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"etherpad\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"etherpad\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"etherpad\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 9001\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_DBID\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"DB_HOST\",\n                    \"value\": \"mariadb\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"DB_PORT\",\n                    \"value\": \"3306\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"etherpad\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"etherpad\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"etherpad\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"centos/etherpad\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"mariadb\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"mariadb:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mariadb\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"mariadb-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"mariadb-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"mariadb\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3306\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"MYSQL_DATABASE\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"MYSQL_PASSWORD\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"MYSQL_ROOT_PASSWORD\",\n                    \"value\": \"etherpad\"\n                  },\n                  {\n                    \"name\": \"MYSQL_USER\",\n                    \"value\": \"etherpad\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"mariadb-claim0\",\n                    \"mountPath\": \"/var/lib/mysql\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"centos/mariadb\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-counter-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-counter-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-counter-v3-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"NodePort\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-counter-v3-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-gitlab-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"10080\",\n            \"port\": 10080,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"10022\",\n            \"port\": 10022,\n            \"targetPort\": 22\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"name\": \"gitlab\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"gitlab\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"NodePort\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"gitlab\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"DB_ADAPTER\",\n                    \"value\": \"postgresql\"\n                  },\n                  {\n                    \"name\": \"DB_HOST\",\n                    \"value\": \"postgresql\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlabhq_production\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"DB_PORT\",\n                    \"value\": \"5432\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DEBUG\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"GITLAB_BACKUP_SCHEDULE\",\n                    \"value\": \"daily\"\n                  },\n                  {\n                    \"name\": \"GITLAB_BACKUP_TIME\",\n                    \"value\": \"01:00\"\n                  },\n                  {\n                    \"name\": \"GITLAB_EMAIL\",\n                    \"value\": \"notifications@example.com\"\n                  },\n                  {\n                    \"name\": \"GITLAB_EMAIL_REPLY_TO\",\n                    \"value\": \"noreply@example.com\"\n                  },\n                  {\n                    \"name\": \"GITLAB_HOST\",\n                    \"value\": \"localhost\"\n                  },\n                  {\n                    \"name\": \"GITLAB_HTTPS\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"GITLAB_INCOMING_EMAIL_ADDRESS\",\n                    \"value\": \"reply@example.com\"\n                  },\n                  {\n                    \"name\": \"GITLAB_NOTIFY_ON_BROKEN_BUILDS\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"GITLAB_NOTIFY_PUSHER\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"GITLAB_PORT\",\n                    \"value\": \"10080\"\n                  },\n                  {\n                    \"name\": \"GITLAB_RELATIVE_URL_ROOT\"\n                  },\n                  {\n                    \"name\": \"GITLAB_ROOT_EMAIL\"\n                  },\n                  {\n                    \"name\": \"GITLAB_ROOT_PASSWORD\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SECRETS_DB_KEY_BASE\",\n                    \"value\": \"long-and-random-alphanumeric-string\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SECRETS_OTP_KEY_BASE\",\n                    \"value\": \"long-and-random-alphanumeric-string\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SECRETS_SECRET_KEY_BASE\",\n                    \"value\": \"long-and-random-alphanumeric-string\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SSH_PORT\",\n                    \"value\": \"10022\"\n                  },\n                  {\n                    \"name\": \"GITLAB_TIMEZONE\",\n                    \"value\": \"Kolkata\"\n                  },\n                  {\n                    \"name\": \"IMAP_ENABLED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"IMAP_HOST\",\n                    \"value\": \"imap.gmail.com\"\n                  },\n                  {\n                    \"name\": \"IMAP_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"IMAP_PORT\",\n                    \"value\": \"993\"\n                  },\n                  {\n                    \"name\": \"IMAP_SSL\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"IMAP_STARTTLS\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"IMAP_USER\",\n                    \"value\": \"mailer@example.com\"\n                  },\n                  {\n                    \"name\": \"OAUTH_ALLOW_SSO\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTH0_CLIENT_ID\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTH0_CLIENT_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTH0_DOMAIN\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTO_LINK_LDAP_USER\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTO_LINK_SAML_USER\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTO_SIGN_IN_WITH_PROVIDER\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AZURE_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AZURE_API_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AZURE_TENANT_ID\"\n                  },\n                  {\n                    \"name\": \"OAUTH_BITBUCKET_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_BITBUCKET_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_BLOCK_AUTO_CREATED_USERS\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_DISABLE_SSL_VERIFICATION\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_LABEL\",\n                    \"value\": \"cas3\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_LOGIN_URL\",\n                    \"value\": \"/cas/login\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_LOGOUT_URL\",\n                    \"value\": \"/cas/logout\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_SERVER\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_VALIDATE_URL\",\n                    \"value\": \"/cas/p3/serviceValidate\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CROWD_APP_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CROWD_APP_PASSWORD\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CROWD_SERVER_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_ENABLED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_EXTERNAL_PROVIDERS\"\n                  },\n                  {\n                    \"name\": \"OAUTH_FACEBOOK_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_FACEBOOK_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_VERIFY_SSL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITLAB_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITLAB_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GOOGLE_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GOOGLE_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GOOGLE_RESTRICT_DOMAIN\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_EXTERNAL_GROUPS\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_GROUPS_ATTRIBUTE\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_IDP_CERT_FINGERPRINT\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_IDP_SSO_TARGET_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ISSUER\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_LABEL\",\n                    \"value\": \"\\\"Our SAML Provider\\\"\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_NAME_IDENTIFIER_FORMAT\",\n                    \"value\": \"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\"\n                  },\n                  {\n                    \"name\": \"OAUTH_TWITTER_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_TWITTER_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"REDIS_HOST\",\n                    \"value\": \"redis\"\n                  },\n                  {\n                    \"name\": \"REDIS_PORT\",\n                    \"value\": \"6379\"\n                  },\n                  {\n                    \"name\": \"SMTP_AUTHENTICATION\",\n                    \"value\": \"login\"\n                  },\n                  {\n                    \"name\": \"SMTP_DOMAIN\",\n                    \"value\": \"www.example.com\"\n                  },\n                  {\n                    \"name\": \"SMTP_ENABLED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"SMTP_HOST\",\n                    \"value\": \"smtp.gmail.com\"\n                  },\n                  {\n                    \"name\": \"SMTP_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"SMTP_PORT\",\n                    \"value\": \"587\"\n                  },\n                  {\n                    \"name\": \"SMTP_STARTTLS\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"SMTP_USER\",\n                    \"value\": \"mailer@example.com\"\n                  },\n                  {\n                    \"name\": \"SSL_SELF_SIGNED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"TZ\",\n                    \"value\": \"Asia/Kolkata\"\n                  }\n                ],\n                \"image\": \"sameersbn/gitlab:8.13.3\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"gitlab\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 22\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/home/git/data\",\n                    \"name\": \"gitlab-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"gitlab-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"gitlab-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"name\": \"postgresql\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"postgresql\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"postgresql\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"DB_EXTENSION\",\n                    \"value\": \"pg_trgm\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlabhq_production\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  }\n                ],\n                \"image\": \"sameersbn/postgresql:9.5-3\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"postgresql\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/lib/postgresql\",\n                    \"name\": \"postgresql-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"postgresql-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"postgresql-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"args\": [\n                  \"--loglevel warning\"\n                ],\n                \"image\": \"sameersbn/redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/lib/redis\",\n                    \"name\": \"redis-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"redis-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"redis-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-gitlab-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"10080\",\n            \"port\": 10080,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"10022\",\n            \"port\": 10022,\n            \"targetPort\": 22\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"NodePort\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"gitlab\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"gitlab:8.13.3\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"gitlab\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"gitlab-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"gitlab-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"gitlab\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 22\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_ADAPTER\",\n                    \"value\": \"postgresql\"\n                  },\n                  {\n                    \"name\": \"DB_HOST\",\n                    \"value\": \"postgresql\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlabhq_production\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"DB_PORT\",\n                    \"value\": \"5432\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DEBUG\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"GITLAB_BACKUP_SCHEDULE\",\n                    \"value\": \"daily\"\n                  },\n                  {\n                    \"name\": \"GITLAB_BACKUP_TIME\",\n                    \"value\": \"01:00\"\n                  },\n                  {\n                    \"name\": \"GITLAB_EMAIL\",\n                    \"value\": \"notifications@example.com\"\n                  },\n                  {\n                    \"name\": \"GITLAB_EMAIL_REPLY_TO\",\n                    \"value\": \"noreply@example.com\"\n                  },\n                  {\n                    \"name\": \"GITLAB_HOST\",\n                    \"value\": \"localhost\"\n                  },\n                  {\n                    \"name\": \"GITLAB_HTTPS\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"GITLAB_INCOMING_EMAIL_ADDRESS\",\n                    \"value\": \"reply@example.com\"\n                  },\n                  {\n                    \"name\": \"GITLAB_NOTIFY_ON_BROKEN_BUILDS\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"GITLAB_NOTIFY_PUSHER\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"GITLAB_PORT\",\n                    \"value\": \"10080\"\n                  },\n                  {\n                    \"name\": \"GITLAB_RELATIVE_URL_ROOT\"\n                  },\n                  {\n                    \"name\": \"GITLAB_ROOT_EMAIL\"\n                  },\n                  {\n                    \"name\": \"GITLAB_ROOT_PASSWORD\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SECRETS_DB_KEY_BASE\",\n                    \"value\": \"long-and-random-alphanumeric-string\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SECRETS_OTP_KEY_BASE\",\n                    \"value\": \"long-and-random-alphanumeric-string\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SECRETS_SECRET_KEY_BASE\",\n                    \"value\": \"long-and-random-alphanumeric-string\"\n                  },\n                  {\n                    \"name\": \"GITLAB_SSH_PORT\",\n                    \"value\": \"10022\"\n                  },\n                  {\n                    \"name\": \"GITLAB_TIMEZONE\",\n                    \"value\": \"Kolkata\"\n                  },\n                  {\n                    \"name\": \"IMAP_ENABLED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"IMAP_HOST\",\n                    \"value\": \"imap.gmail.com\"\n                  },\n                  {\n                    \"name\": \"IMAP_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"IMAP_PORT\",\n                    \"value\": \"993\"\n                  },\n                  {\n                    \"name\": \"IMAP_SSL\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"IMAP_STARTTLS\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"IMAP_USER\",\n                    \"value\": \"mailer@example.com\"\n                  },\n                  {\n                    \"name\": \"OAUTH_ALLOW_SSO\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTH0_CLIENT_ID\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTH0_CLIENT_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTH0_DOMAIN\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTO_LINK_LDAP_USER\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTO_LINK_SAML_USER\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AUTO_SIGN_IN_WITH_PROVIDER\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AZURE_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AZURE_API_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_AZURE_TENANT_ID\"\n                  },\n                  {\n                    \"name\": \"OAUTH_BITBUCKET_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_BITBUCKET_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_BLOCK_AUTO_CREATED_USERS\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_DISABLE_SSL_VERIFICATION\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_LABEL\",\n                    \"value\": \"cas3\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_LOGIN_URL\",\n                    \"value\": \"/cas/login\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_LOGOUT_URL\",\n                    \"value\": \"/cas/logout\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_SERVER\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CAS3_VALIDATE_URL\",\n                    \"value\": \"/cas/p3/serviceValidate\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CROWD_APP_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CROWD_APP_PASSWORD\"\n                  },\n                  {\n                    \"name\": \"OAUTH_CROWD_SERVER_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_ENABLED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"OAUTH_EXTERNAL_PROVIDERS\"\n                  },\n                  {\n                    \"name\": \"OAUTH_FACEBOOK_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_FACEBOOK_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITHUB_VERIFY_SSL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITLAB_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GITLAB_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GOOGLE_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GOOGLE_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"OAUTH_GOOGLE_RESTRICT_DOMAIN\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_EXTERNAL_GROUPS\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_GROUPS_ATTRIBUTE\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_IDP_CERT_FINGERPRINT\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_IDP_SSO_TARGET_URL\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_ISSUER\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_LABEL\",\n                    \"value\": \"\\\"Our SAML Provider\\\"\"\n                  },\n                  {\n                    \"name\": \"OAUTH_SAML_NAME_IDENTIFIER_FORMAT\",\n                    \"value\": \"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\"\n                  },\n                  {\n                    \"name\": \"OAUTH_TWITTER_API_KEY\"\n                  },\n                  {\n                    \"name\": \"OAUTH_TWITTER_APP_SECRET\"\n                  },\n                  {\n                    \"name\": \"REDIS_HOST\",\n                    \"value\": \"redis\"\n                  },\n                  {\n                    \"name\": \"REDIS_PORT\",\n                    \"value\": \"6379\"\n                  },\n                  {\n                    \"name\": \"SMTP_AUTHENTICATION\",\n                    \"value\": \"login\"\n                  },\n                  {\n                    \"name\": \"SMTP_DOMAIN\",\n                    \"value\": \"www.example.com\"\n                  },\n                  {\n                    \"name\": \"SMTP_ENABLED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"SMTP_HOST\",\n                    \"value\": \"smtp.gmail.com\"\n                  },\n                  {\n                    \"name\": \"SMTP_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"SMTP_PORT\",\n                    \"value\": \"587\"\n                  },\n                  {\n                    \"name\": \"SMTP_STARTTLS\",\n                    \"value\": \"true\"\n                  },\n                  {\n                    \"name\": \"SMTP_USER\",\n                    \"value\": \"mailer@example.com\"\n                  },\n                  {\n                    \"name\": \"SSL_SELF_SIGNED\",\n                    \"value\": \"false\"\n                  },\n                  {\n                    \"name\": \"TZ\",\n                    \"value\": \"Asia/Kolkata\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"gitlab-claim0\",\n                    \"mountPath\": \"/home/git/data\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"8.13.3\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"sameersbn/gitlab:8.13.3\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"postgresql\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"postgresql:9.5-3\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"postgresql\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"postgresql-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"postgresql-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"postgresql\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_EXTENSION\",\n                    \"value\": \"pg_trgm\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlabhq_production\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"postgresql-claim0\",\n                    \"mountPath\": \"/var/lib/postgresql\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"9.5-3\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"sameersbn/postgresql:9.5-3\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"redis-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"redis-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"args\": [\n                  \"--loglevel warning\"\n                ],\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"redis-claim0\",\n                    \"mountPath\": \"/var/lib/redis\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"sameersbn/redis:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            },\n            \"annotations\": {\n              \"kompose.service.type\": \"LoadBalancer\",\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"frontend\",\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {}\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            },\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-master\",\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {}\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            },\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-replica\",\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {}\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"frontend\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"frontend:v4\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"frontend\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"v4\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"gcr.io/google-samples/gb-frontend:v4\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-master\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-master:e2e\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-master\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"e2e\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis:e2e\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-replica\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-replica:v1\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-replica\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"v1\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis-slave:v2\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-v3-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"name\": \"frontend\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"frontend\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"LoadBalancer\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"frontend\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"name\": \"redis-master\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-master\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-master\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"name\": \"redis-replica\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-replica\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-replica\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-v3-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"frontend\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"frontend:v4\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"frontend\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"v4\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"gcr.io/google-samples/gb-frontend:v4\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-master\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-master:e2e\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-master\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"e2e\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis:e2e\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-replica\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-replica:v1\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-replica\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"v1\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis-slave:v2\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-voting-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Postgres Database\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"result\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"result\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5001\",\n            \"port\": 5001,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"result\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"vote\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Vote\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"vote\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"com.example.description\": \"Postgres Database\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"name\": \"db\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"db\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"com.example.description\": \"Postgres Database\",\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"postgres:9.4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"db\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:alpine\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"result\"\n        },\n        \"name\": \"result\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"result\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"result\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tmadams333/example-voting-app-result:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"result\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"com.example.description\": \"Vote\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"name\": \"vote\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"vote\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"com.example.description\": \"Vote\",\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"vote\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"docker/example-voting-app-vote:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"vote\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"worker\"\n        },\n        \"name\": \"worker\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"worker\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"worker\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"docker/example-voting-app-worker:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"worker\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/examples/output-voting-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Postgres Database\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"result\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"result\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5001\",\n            \"port\": 5001,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"result\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"vote\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Vote\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"vote\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Postgres Database\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"db\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"db:9.4\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"db\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"9.4\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"postgres:9.4\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:alpine\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"alpine\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:alpine\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"result\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"result\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"result\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"result:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"result\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"result\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"result\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"result\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"result\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tmadams333/example-voting-app-result:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"vote\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Vote\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"vote\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"vote:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"vote\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"vote\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"vote\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"docker/example-voting-app-vote:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"worker\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"worker\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"worker\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"worker:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"worker\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"worker\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"worker\",\n                \"image\": \" \",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"worker\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"worker\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"docker/example-voting-app-worker:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/expose/compose.yaml",
    "content": "services:\n  web:\n    image: tuna/docker-counter23\n    ports:\n      - \"5000:5000\"\n    links:\n      - redis\n    labels:\n      kompose.service.expose: \"batman.example.com/dev,batwoman.example.com\"\n      kompose.service.expose.tls-secret: \"test-secret\"\n      kompose.service.expose.ingress-class-name: \"nginx\"\n  redis:\n    image: redis:3.0\n    ports:\n      - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/expose/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: redis:3.0\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: tuna/docker-counter23\n          name: web\n          ports:\n            - containerPort: 5000\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ingressClassName: nginx\n  rules:\n    - host: batman.example.com\n      http:\n        paths:\n          - backend:\n              service:\n                name: web\n                port:\n                  number: 5000\n            path: /dev\n            pathType: Prefix\n    - host: batwoman.example.com\n      http:\n        paths:\n          - backend:\n              service:\n                name: web\n                port:\n                  number: 5000\n            path: /\n            pathType: Prefix\n  tls:\n    - hosts:\n        - batman.example.com\n        - batwoman.example.com\n      secretName: test-secret\n\n"
  },
  {
    "path": "script/test/fixtures/expose/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  ports:\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: ' '\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:3.0\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis:3.0\n      name: \"3.0\"\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: ' '\n          name: web\n          ports:\n            - containerPort: 5000\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: tuna/docker-counter23\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nkind: Route\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  host: batman.example.com/dev,batwoman.example.com\n  port:\n    targetPort: 5000\n  to:\n    kind: Service\n    name: web\n\n"
  },
  {
    "path": "script/test/fixtures/external-traffic-policy/compose-v1.yaml",
    "content": "\nservices:\n  front-end:\n    image: gcr.io/google-samples/gb-frontend:v4\n    environment:\n      - GET_HOSTS_FROM=dns\n    ports:\n      - 80:80\n    labels:\n      kompose.service.expose: lb\n      kompose.service.expose.ingress-class-name: nginx\n      kompose.service.external-traffic-policy: local\n      kompose.service.type: loadbalancer\n"
  },
  {
    "path": "script/test/fixtures/external-traffic-policy/compose-v2.yaml",
    "content": "\nservices:\n  front-end:\n    image: gcr.io/google-samples/gb-frontend:v4\n    environment:\n      - GET_HOSTS_FROM=dns\n    ports:\n      - 80:80\n    labels:\n      kompose.service.expose: lb\n      kompose.service.expose.ingress-class-name: nginx\n      kompose.service.external-traffic-policy: local\n      kompose.service.type: headless\n"
  },
  {
    "path": "script/test/fixtures/external-traffic-policy/output-k8s-v1.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: front-end-tcp\n  name: front-end-tcp\nspec:\n  externalTrafficPolicy: Local\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: front-end\n  type: LoadBalancer\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: front-end\n  template:\n    metadata:\n      labels:\n        io.kompose.service: front-end\n    spec:\n      containers:\n        - env:\n            - name: GET_HOSTS_FROM\n              value: dns\n          image: gcr.io/google-samples/gb-frontend:v4\n          name: front-end\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/external-traffic-policy/output-k8s-v2.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  clusterIP: None\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: front-end\n  type: ClusterIP\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: front-end\n  template:\n    metadata:\n      labels:\n        io.kompose.service: front-end\n    spec:\n      containers:\n        - env:\n            - name: GET_HOSTS_FROM\n              value: dns\n          image: gcr.io/google-samples/gb-frontend:v4\n          name: front-end\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  ingressClassName: nginx\n  rules:\n    - host: lb\n      http:\n        paths:\n          - backend:\n              service:\n                name: front-end\n                port:\n                  number: 80\n            path: /\n            pathType: Prefix\n\n"
  },
  {
    "path": "script/test/fixtures/external-traffic-policy/output-os-v1.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: front-end-tcp\n  name: front-end-tcp\nspec:\n  externalTrafficPolicy: Local\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: front-end\n  type: LoadBalancer\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: front-end\n  template:\n    metadata:\n      labels:\n        io.kompose.service: front-end\n    spec:\n      containers:\n        - env:\n            - name: GET_HOSTS_FROM\n              value: dns\n          image: ' '\n          name: front-end\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - front-end\n        from:\n          kind: ImageStreamTag\n          name: front-end:v4\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: gcr.io/google-samples/gb-frontend:v4\n      name: v4\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/external-traffic-policy/output-os-v2.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  clusterIP: None\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: front-end\n  type: ClusterIP\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: front-end\n  template:\n    metadata:\n      labels:\n        io.kompose.service: front-end\n    spec:\n      containers:\n        - env:\n            - name: GET_HOSTS_FROM\n              value: dns\n          image: ' '\n          name: front-end\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - front-end\n        from:\n          kind: ImageStreamTag\n          name: front-end:v4\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: gcr.io/google-samples/gb-frontend:v4\n      name: v4\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nkind: Route\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  host: lb\n  port:\n    targetPort: 80\n  to:\n    kind: Service\n    name: front-end\n\n"
  },
  {
    "path": "script/test/fixtures/fsgroup/compose.yaml",
    "content": "volumes:\n  pgadmin-data:\n\nservices:\n  pgadmin:\n    labels:\n      kompose.security-context.fsgroup: 1001\n    image: dpage/pgadmin4\n    environment:\n      PGADMIN_DEFAULT_EMAIL: dumb_pgadmin_user@email.com\n      PGADMIN_DEFAULT_PASSWORD: pgadmin_password\n    volumes:\n      - pgadmin-data:/var/lib/pgadmin\n"
  },
  {
    "path": "script/test/fixtures/fsgroup/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: pgadmin\n  name: pgadmin\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: pgadmin\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: pgadmin\n    spec:\n      containers:\n        - env:\n            - name: PGADMIN_DEFAULT_EMAIL\n              value: dumb_pgadmin_user@email.com\n            - name: PGADMIN_DEFAULT_PASSWORD\n              value: pgadmin_password\n          image: dpage/pgadmin4\n          name: pgadmin\n          volumeMounts:\n            - mountPath: /var/lib/pgadmin\n              name: pgadmin-data\n      restartPolicy: Always\n      securityContext:\n        fsGroup: 1001\n      volumes:\n        - name: pgadmin-data\n          persistentVolumeClaim:\n            claimName: pgadmin-data\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: pgadmin-data\n  name: pgadmin-data\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n"
  },
  {
    "path": "script/test/fixtures/fsgroup/output-os.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: pgadmin\n  name: pgadmin\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: pgadmin\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: pgadmin\n    spec:\n      containers:\n        - env:\n            - name: PGADMIN_DEFAULT_EMAIL\n              value: dumb_pgadmin_user@email.com\n            - name: PGADMIN_DEFAULT_PASSWORD\n              value: pgadmin_password\n          image: ' '\n          name: pgadmin\n          volumeMounts:\n            - mountPath: /var/lib/pgadmin\n              name: pgadmin-data\n      restartPolicy: Always\n      securityContext:\n        fsGroup: 1001\n      volumes:\n        - name: pgadmin-data\n          persistentVolumeClaim:\n            claimName: pgadmin-data\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - pgadmin\n        from:\n          kind: ImageStreamTag\n          name: pgadmin:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: pgadmin\n  name: pgadmin\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: dpage/pgadmin4\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: pgadmin-data\n  name: pgadmin-data\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n"
  },
  {
    "path": "script/test/fixtures/gitlab/README.md",
    "content": "## Gitlab\n\nGitlab, Postgresql, Redis\n\n### Usage\n\nThe simplest thing to do:\n\n```bash\nexport $(cat envs)\ndocker-compose up\n```\n\nTo customize the values edit `envs` file.\n"
  },
  {
    "path": "script/test/fixtures/gitlab/docker-compose.yml",
    "content": "\nservices:\n  postgresql:\n    image: swordphilic/postgresql\n    ports:\n      - \"$DB_PORT\"\n    environment:\n      DB_NAME: $DB_NAME\n      DB_PASS: $DB_PASS\n      DB_USER: $DB_USER\n\n  gitlab:\n    image: swordphilic/gitlab\n    ports:\n      - \"30000:80\"\n      - \"30001:443\"\n      - \"30002:22\"\n    restart: always\n    environment:\n      DB_TYPE: postgres\n      DB_HOST: postgresql\n      DB_PORT: $DB_PORT\n      DB_NAME: $DB_NAME\n      DB_PASS: $DB_PASS\n      DB_USER: $DB_USER\n      REDIS_HOST: redis\n      REDIS_PORT: $REDIS_PORT\n\n  redis:\n    image: swordphilic/redis\n    ports:\n      - $REDIS_PORT\n"
  },
  {
    "path": "script/test/fixtures/gitlab/envs",
    "content": "DB_PORT=5432\nDB_NAME=gitlab\nDB_PASS=gitlab\nDB_USER=gitlab\nREDIS_PORT=6379\n"
  },
  {
    "path": "script/test/fixtures/gitlab/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"30000\",\n            \"port\": 30000,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"30001\",\n            \"port\": 30001,\n            \"targetPort\": 443\n          },\n          {\n            \"name\": \"30002\",\n            \"port\": 30002,\n            \"targetPort\": 22\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"gitlab\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"name\": \"gitlab\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"gitlab\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"gitlab\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"DB_HOST\",\n                    \"value\": \"postgresql\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_PORT\",\n                    \"value\": \"5432\"\n                  },\n                  {\n                    \"name\": \"DB_TYPE\",\n                    \"value\": \"postgres\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"REDIS_HOST\",\n                    \"value\": \"redis\"\n                  },\n                  {\n                    \"name\": \"REDIS_PORT\",\n                    \"value\": \"6379\"\n                  }\n                ],\n                \"image\": \"swordphilic/gitlab\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"gitlab\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 443\n                  },\n                  {\n                    \"containerPort\": 22\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"name\": \"postgresql\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"postgresql\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"postgresql\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  }\n                ],\n                \"image\": \"swordphilic/postgresql\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"postgresql\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"swordphilic/redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/gitlab/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"30000\",\n            \"port\": 30000,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"30001\",\n            \"port\": 30001,\n            \"targetPort\": 443\n          },\n          {\n            \"name\": \"30002\",\n            \"port\": 30002,\n            \"targetPort\": 22\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"gitlab\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"gitlab\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"gitlab:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"gitlab\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"gitlab\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"gitlab\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 443\n                  },\n                  {\n                    \"containerPort\": 22\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_HOST\",\n                    \"value\": \"postgresql\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_PORT\",\n                    \"value\": \"5432\"\n                  },\n                  {\n                    \"name\": \"DB_TYPE\",\n                    \"value\": \"postgres\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"REDIS_HOST\",\n                    \"value\": \"redis\"\n                  },\n                  {\n                    \"name\": \"REDIS_PORT\",\n                    \"value\": \"6379\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"gitlab\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"gitlab\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"swordphilic/gitlab\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"postgresql\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"postgresql:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"postgresql\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"postgresql\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"gitlab\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"swordphilic/postgresql\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"swordphilic/redis\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/healthcheck/compose-healthcheck.yaml",
    "content": "services:\n  # test exec\n  redis:\n    image: redis\n    ports:\n      - \"6379\"\n    healthcheck:\n      test: echo \"liveness\"\n      interval: 10s\n      timeout: 1s\n      retries: 5\n    labels:\n      kompose.service.healthcheck.readiness.test: echo \"liveness\"\n      kompose.service.healthcheck.readiness.interval: 10s\n      kompose.service.healthcheck.readiness.timeout: 1s\n      kompose.service.healthcheck.readiness.retries: 5\n\n  # test http get\n  postgresql:\n    image: postgresql\n    ports:\n      - \"5432\"\n    healthcheck:\n      interval: 10s\n      timeout: 1s\n      retries: 5\n    labels:\n      kompose.service.healthcheck.liveness.http_get_path: /health\n      kompose.service.healthcheck.liveness.http_get_port: 8080\n      kompose.service.healthcheck.readiness.http_get_path: /ready\n      kompose.service.healthcheck.readiness.http_get_port: 8080\n      kompose.service.healthcheck.readiness.interval: 10s\n      kompose.service.healthcheck.readiness.timeout: 1s\n      kompose.service.healthcheck.readiness.retries: 5\n\n  # test tcp socket\n  mongo:\n    image: mongo\n    ports:\n      - \"27017\"\n    healthcheck:\n      interval: 10s\n      timeout: 1s\n      retries: 5\n    labels:\n      kompose.service.group: \"my-group\"\n      kompose.service.healthcheck.liveness.tcp_port: 8080\n      kompose.service.healthcheck.readiness.tcp_port: 9090\n      kompose.service.healthcheck.readiness.interval: 10s\n      kompose.service.healthcheck.readiness.timeout: 1s\n      kompose.service.healthcheck.readiness.retries: 5\n\n  # test multiple service merge\n  mysql:\n    image: mysql\n    ports:\n      - \"3306\"\n    healthcheck:\n      interval: 11s\n      timeout: 2s\n      retries: 6\n    labels:\n      kompose.service.group: \"my-group\"\n      kompose.service.healthcheck.liveness.tcp_port: 8081\n      kompose.service.healthcheck.readiness.tcp_port: 9091\n      kompose.service.healthcheck.readiness.interval: 11s\n      kompose.service.healthcheck.readiness.timeout: 2s\n      kompose.service.healthcheck.readiness.retries: 6\n"
  },
  {
    "path": "script/test/fixtures/healthcheck/output-healthcheck-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: mongo\n  name: mongo\nspec:\n  ports:\n    - name: \"27017\"\n      port: 27017\n      targetPort: 27017\n  selector:\n    io.kompose.service: mongo\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: mysql\n  name: mysql\nspec:\n  ports:\n    - name: \"3306\"\n      port: 3306\n      targetPort: 3306\n  selector:\n    io.kompose.service: mysql\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: postgresql\n  name: postgresql\nspec:\n  ports:\n    - name: \"5432\"\n      port: 5432\n      targetPort: 5432\n  selector:\n    io.kompose.service: postgresql\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: mongo\n  name: mongo\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: mongo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: mongo\n    spec:\n      containers:\n        - image: mongo\n          livenessProbe:\n            failureThreshold: 5\n            periodSeconds: 10\n            tcpSocket:\n              port: 8080\n            timeoutSeconds: 1\n          name: mongo\n          ports:\n            - containerPort: 27017\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 5\n            periodSeconds: 10\n            tcpSocket:\n              port: 9090\n            timeoutSeconds: 1\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: mysql\n  name: mysql\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: mysql\n  template:\n    metadata:\n      labels:\n        io.kompose.service: mysql\n    spec:\n      containers:\n        - image: mysql\n          livenessProbe:\n            failureThreshold: 6\n            periodSeconds: 11\n            tcpSocket:\n              port: 8081\n            timeoutSeconds: 2\n          name: mysql\n          ports:\n            - containerPort: 3306\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 6\n            periodSeconds: 11\n            tcpSocket:\n              port: 9091\n            timeoutSeconds: 2\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: postgresql\n  name: postgresql\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: postgresql\n  template:\n    metadata:\n      labels:\n        io.kompose.service: postgresql\n    spec:\n      containers:\n        - image: postgresql\n          livenessProbe:\n            failureThreshold: 5\n            httpGet:\n              path: /health\n              port: 8080\n            periodSeconds: 10\n            timeoutSeconds: 1\n          name: postgresql\n          ports:\n            - containerPort: 5432\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 5\n            httpGet:\n              path: /ready\n              port: 8080\n            periodSeconds: 10\n            timeoutSeconds: 1\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: redis\n          livenessProbe:\n            exec:\n              command:\n                - echo \"liveness\"\n            failureThreshold: 5\n            periodSeconds: 10\n            timeoutSeconds: 1\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n          readinessProbe:\n            exec:\n              command:\n                - echo\n                - liveness\n            failureThreshold: 5\n            periodSeconds: 10\n            timeoutSeconds: 1\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/healthcheck/output-healthcheck-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: mongo\n  name: mongo\nspec:\n  ports:\n    - name: \"27017\"\n      port: 27017\n      targetPort: 27017\n  selector:\n    io.kompose.service: mongo\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: mysql\n  name: mysql\nspec:\n  ports:\n    - name: \"3306\"\n      port: 3306\n      targetPort: 3306\n  selector:\n    io.kompose.service: mysql\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: postgresql\n  name: postgresql\nspec:\n  ports:\n    - name: \"5432\"\n      port: 5432\n      targetPort: 5432\n  selector:\n    io.kompose.service: postgresql\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: mongo\n  name: mongo\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: mongo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: mongo\n    spec:\n      containers:\n        - image: ' '\n          livenessProbe:\n            failureThreshold: 5\n            periodSeconds: 10\n            tcpSocket:\n              port: 8080\n            timeoutSeconds: 1\n          name: mongo\n          ports:\n            - containerPort: 27017\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 5\n            periodSeconds: 10\n            tcpSocket:\n              port: 9090\n            timeoutSeconds: 1\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - mongo\n        from:\n          kind: ImageStreamTag\n          name: mongo:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: mongo\n  name: mongo\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: mongo\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: mysql\n  name: mysql\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: mysql\n  template:\n    metadata:\n      labels:\n        io.kompose.service: mysql\n    spec:\n      containers:\n        - image: ' '\n          livenessProbe:\n            failureThreshold: 6\n            periodSeconds: 11\n            tcpSocket:\n              port: 8081\n            timeoutSeconds: 2\n          name: mysql\n          ports:\n            - containerPort: 3306\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 6\n            periodSeconds: 11\n            tcpSocket:\n              port: 9091\n            timeoutSeconds: 2\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - mysql\n        from:\n          kind: ImageStreamTag\n          name: mysql:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: mysql\n  name: mysql\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: mysql\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: postgresql\n  name: postgresql\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: postgresql\n  template:\n    metadata:\n      labels:\n        io.kompose.service: postgresql\n    spec:\n      containers:\n        - image: ' '\n          livenessProbe:\n            failureThreshold: 5\n            httpGet:\n              path: /health\n              port: 8080\n            periodSeconds: 10\n            timeoutSeconds: 1\n          name: postgresql\n          ports:\n            - containerPort: 5432\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 5\n            httpGet:\n              path: /ready\n              port: 8080\n            periodSeconds: 10\n            timeoutSeconds: 1\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - postgresql\n        from:\n          kind: ImageStreamTag\n          name: postgresql:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: postgresql\n  name: postgresql\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: postgresql\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: ' '\n          livenessProbe:\n            exec:\n              command:\n                - echo \"liveness\"\n            failureThreshold: 5\n            periodSeconds: 10\n            timeoutSeconds: 1\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n          readinessProbe:\n            exec:\n              command:\n                - echo\n                - liveness\n            failureThreshold: 5\n            periodSeconds: 10\n            timeoutSeconds: 1\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/host-port-protocol/compose.yaml",
    "content": "\nservices:\n  nginx:\n    labels:\n      kompose.container.kompose.controller.port.expose: true\n    ports:\n      - target: 80\n        published: 80\n        protocol: tcp\n        mode: host\n    image: nginx\n"
  },
  {
    "path": "script/test/fixtures/host-port-protocol/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: nginx\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: nginx\n  template:\n    metadata:\n      labels:\n        io.kompose.service: nginx\n    spec:\n      containers:\n        - image: nginx\n          name: nginx\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/host-port-protocol/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: nginx\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: nginx\n  template:\n    metadata:\n      labels:\n        io.kompose.service: nginx\n    spec:\n      containers:\n        - image: ' '\n          name: nginx\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - nginx\n        from:\n          kind: ImageStreamTag\n          name: nginx:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/hpa/compose.yaml",
    "content": "services:\n  web:\n    image: nginx\n    labels:\n      kompose.hpa.cpu: 50\n      kompose.hpa.memory: 70\n      kompose.hpa.replicas.min: 1\n      kompose.hpa.replicas.max: 10\n\n"
  },
  {
    "path": "script/test/fixtures/hpa/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx\n          name: web\n      restartPolicy: Always\n\n---\napiVersion: autoscaling/v2\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: web\nspec:\n  maxReplicas: 10\n  metrics:\n    - resource:\n        name: cpu\n        target:\n          averageUtilization: 50\n          type: Utilization\n      type: Resource\n    - resource:\n        name: memory\n        target:\n          averageUtilization: 70\n          type: Utilization\n      type: Resource\n  minReplicas: 1\n  scaleTargetRef:\n    apiVersion: apps/v1\n    kind: Deployment\n    name: web\n\n"
  },
  {
    "path": "script/test/fixtures/image-pull-policy/compose-files/v12-fail-image-pull-policy.yml",
    "content": "services:\n  nginx0:\n    image: nginx\n    labels:\n      kompose.image-pull-policy: \"Fail\"\n"
  },
  {
    "path": "script/test/fixtures/image-pull-policy/compose-files/v12-image-pull-policy.yml",
    "content": "services:\n  nginx0:\n    image: nginx\n    labels:\n      kompose.image-pull-policy: \"Always\"\n\n"
  },
  {
    "path": "script/test/fixtures/image-pull-policy/compose-files/v3-image-pull-policy.yml",
    "content": "services:\n  nginx0:\n    image: nginx\n    labels:\n      kompose.image-pull-policy: \"Always\"\n  nginx1:\n    image: nginx\n    labels:\n      kompose.image-pull-policy: \"IfNotPresent\"\n  nginx2:\n    image: nginx\n    labels:\n      kompose.image-pull-policy: \"Never\"\n"
  },
  {
    "path": "script/test/fixtures/image-pull-policy/provider-files/kubernetes-v12-image-pull-policy.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.image-pull-policy\": \"Always\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx0\"\n        },\n        \"name\": \"nginx0\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx0\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.image-pull-policy\": \"Always\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx0\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"Always\",\n                \"name\": \"nginx0\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/image-pull-policy/provider-files/kubernetes-v3-image-pull-policy.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.image-pull-policy\": \"Always\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx0\"\n        },\n        \"name\": \"nginx0\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx0\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.image-pull-policy\": \"Always\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx0\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"Always\",\n                \"name\": \"nginx0\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.image-pull-policy\": \"IfNotPresent\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx1\"\n        },\n        \"name\": \"nginx1\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx1\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.image-pull-policy\": \"IfNotPresent\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"IfNotPresent\",\n                \"name\": \"nginx1\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.image-pull-policy\": \"Never\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx2\"\n        },\n        \"name\": \"nginx2\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx2\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.image-pull-policy\": \"Never\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx2\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"Never\",\n                \"name\": \"nginx2\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/image-pull-secret/compose-files/docker-compose-image-pull-secret.yml",
    "content": "tm-image-service:\n  image: premium/private-image\n  labels:\n    kompose.image-pull-secret: \"sample-k8s-secret-name\"\nopen-image-service:\n  image: nginx-alpine\n"
  },
  {
    "path": "script/test/fixtures/image-pull-secret/provider-files/kubernetes-image-pull-secret.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"open-image-service\"\n        },\n        \"name\": \"open-image-service\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"open-image-service\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"open-image-service\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx-alpine\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"open-image-service\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.image-pull-secret\": \"sample-k8s-secret-name\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"tm-image-service\"\n        },\n        \"name\": \"tm-image-service\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"tm-image-service\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.image-pull-secret\": \"sample-k8s-secret-name\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"tm-image-service\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"premium/private-image\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"tm-image-service\",\n                \"resources\": {}\n              }\n            ],\n            \"imagePullSecrets\": [\n              {\n                \"name\": \"sample-k8s-secret-name\"\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/initcontainer/compose.yaml",
    "content": "services:\n  web:\n    image: nginx\n    labels:\n      kompose.init.containers.name: \"init-myservice\"\n      kompose.init.containers.image: \"busybox:1.28\"\n      kompose.init.containers.command: '[\"sh\", \"-c\", \"until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done\"]'"
  },
  {
    "path": "script/test/fixtures/initcontainer/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx\n          name: web\n      initContainers:\n        - command:\n            - sh\n            - -c\n            - until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done\n          image: busybox:1.28\n          name: init-myservice\n      restartPolicy: Always"
  },
  {
    "path": "script/test/fixtures/keyonly-envs/env.yml",
    "content": "\nservices:\n  redis-master:\n    image: registry.k8s.io/redis:e2e \n    ports:\n      - \"6379\"\n  redis-replica:\n    image: registry.k8s.io/redis-slave:v2\n    ports:\n      - \"6379\"\n    environment:\n      - GET_HOSTS_FROM=dns\n      - RACK_ENV=development\n      - SHOW=true\n      - SESSION_SECRET\n  frontend:\n    image: gcr.io/google-samples/gb-frontend:v4\n    ports:\n      - \"80:80\"\n    environment:\n      GET_HOSTS_FROM: dns\n      RACK_ENV: development\n      SHOW: 'true'\n      SESSION_SECRET:\n"
  },
  {
    "path": "script/test/fixtures/keyonly-envs/envs",
    "content": "SESSION_SECRET=session\n"
  },
  {
    "path": "script/test/fixtures/keyonly-envs/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"name\": \"frontend\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"frontend\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  },\n                  {\n                    \"name\": \"RACK_ENV\",\n                    \"value\": \"development\"\n                  },\n                  {\n                    \"name\": \"SESSION_SECRET\",\n                    \"value\": \"session\"\n                  },\n                  {\n                    \"name\": \"SHOW\",\n                    \"value\": \"true\"\n                  }\n                ],\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"frontend\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"name\": \"redis-master\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-master\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-master\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"name\": \"redis-replica\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-replica\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  },\n                  {\n                    \"name\": \"RACK_ENV\",\n                    \"value\": \"development\"\n                  },\n                  {\n                    \"name\": \"SESSION_SECRET\",\n                    \"value\": \"session\"\n                  },\n                  {\n                    \"name\": \"SHOW\",\n                    \"value\": \"true\"\n                  }\n                ],\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-replica\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/label/compose.yaml",
    "content": "services:\n  app:\n    image: node:18-alpine\n    ports:\n      - 3000:3000\n    labels:\n      - \"com.example.label=foo\"\n"
  },
  {
    "path": "script/test/fixtures/label/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    com.example.label: foo\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  ports:\n    - name: \"3000\"\n      port: 3000\n      targetPort: 3000\n  selector:\n    io.kompose.service: app\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  annotations:\n    com.example.label: foo\n  labels:\n    io.kompose.service: app\n  name: app\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: app\n  template:\n    metadata:\n      annotations:\n        com.example.label: foo\n      labels:\n        io.kompose.service: app\n    spec:\n      containers:\n        - image: node:18-alpine\n          name: app\n          ports:\n            - containerPort: 3000\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/label-port/docker-compose.yml",
    "content": "services:\n  webapiapplication:\n    image: webapiapplication\n    labels:\n      kompose.service.type: NodePort\n"
  },
  {
    "path": "script/test/fixtures/multiple-files/first.yaml",
    "content": "services:\n  foo:\n    image: foo\n    deploy:\n      replicas: 3\n\n  bar:\n    image: bar"
  },
  {
    "path": "script/test/fixtures/multiple-files/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: bar\n  name: bar\nspec:\n  replicas: 99\n  selector:\n    matchLabels:\n      io.kompose.service: bar\n  template:\n    metadata:\n      labels:\n        io.kompose.service: bar\n    spec:\n      containers:\n        - image: bar\n          name: bar\n      restartPolicy: Always\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      io.kompose.service: foo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: foo\n    spec:\n      containers:\n        - image: foo\n          name: foo\n      restartPolicy: Always\n\n\n"
  },
  {
    "path": "script/test/fixtures/multiple-files/output-os.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: bar\n  name: bar\nspec:\n  replicas: 99\n  selector:\n    io.kompose.service: bar\n  template:\n    metadata:\n      labels:\n        io.kompose.service: bar\n    spec:\n      containers:\n        - image: ' '\n          name: bar\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - bar\n        from:\n          kind: ImageStreamTag\n          name: bar:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: bar\n  name: bar\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: bar\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  replicas: 3\n  selector:\n    io.kompose.service: foo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: foo\n    spec:\n      containers:\n        - image: ' '\n          name: foo\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - foo\n        from:\n          kind: ImageStreamTag\n          name: foo:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: foo\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/multiple-files/second.yaml",
    "content": "services:\n  bar:\n    deploy:\n      replicas: 99"
  },
  {
    "path": "script/test/fixtures/multiple-type-volumes/compose.yaml",
    "content": "services:\n  web:\n    image: nginx\n    volumes:\n      - ./tls:/etc/tls\n      - ./tls/a.key:/etc/test-a-key.key\n    labels:\n      kompose.volume.type: configMap\n  db:\n    image: mysql\n    volumes:\n      - db-data:/var/lib/mysql\n    labels:\n      kompose.volume.type: persistentVolumeClaim\n\nvolumes:\n  db-data:\n"
  },
  {
    "path": "script/test/fixtures/multiple-type-volumes/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: mysql\n          name: db\n          volumeMounts:\n            - mountPath: /var/lib/mysql\n              name: db-data\n      restartPolicy: Always\n      volumes:\n        - name: db-data\n          persistentVolumeClaim:\n            claimName: db-data\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: db-data\n  name: db-data\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx\n          name: web\n          volumeMounts:\n            - mountPath: /etc/tls\n              name: web-cm0\n            - mountPath: /etc/test-a-key.key\n              name: web-cm1\n              subPath: test-a-key.key\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: web-cm0\n          name: web-cm0\n        - configMap:\n            items:\n              - key: a.key\n                path: test-a-key.key\n            name: web-cm1\n          name: web-cm1\n\n---\napiVersion: v1\ndata:\n  a.crt: test-crt-data...\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web-cm0\n\n---\napiVersion: v1\ndata:\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: web\n  name: web-cm1\n\n"
  },
  {
    "path": "script/test/fixtures/multiple-type-volumes/output-os.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: ' '\n          name: db\n          volumeMounts:\n            - mountPath: /var/lib/mysql\n              name: db-data\n      restartPolicy: Always\n      volumes:\n        - name: db-data\n          persistentVolumeClaim:\n            claimName: db-data\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - db\n        from:\n          kind: ImageStreamTag\n          name: db:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: mysql\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: db-data\n  name: db-data\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: ' '\n          name: web\n          volumeMounts:\n            - mountPath: /etc/tls\n              name: web-cm0\n            - mountPath: /etc/test-a-key.key\n              name: web-cm1\n              subPath: test-a-key.key\n      restartPolicy: Always\n      volumes:\n        - configMap:\n            name: web-cm0\n          name: web-cm0\n        - configMap:\n            items:\n              - key: a.key\n                path: test-a-key.key\n            name: web-cm1\n          name: web-cm1\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\ndata:\n  a.crt: test-crt-data...\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web-cm0\n\n---\napiVersion: v1\ndata:\n  a.key: test-key-data....\nkind: ConfigMap\nmetadata:\n  annotations:\n    use-subpath: \"true\"\n  labels:\n    io.kompose.service: web\n  name: web-cm1\n\n"
  },
  {
    "path": "script/test/fixtures/multiple-type-volumes/tls/a.crt",
    "content": "test-crt-data..."
  },
  {
    "path": "script/test/fixtures/multiple-type-volumes/tls/a.key",
    "content": "test-key-data...."
  },
  {
    "path": "script/test/fixtures/namespace/compose.yaml",
    "content": "services:\n  web:\n    image: nginx\n    ports:\n    - 80:80\n"
  },
  {
    "path": "script/test/fixtures/namespace/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\n  namespace: web\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: web\n\n\n---\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: web\n  namespace: web\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\n  namespace: web\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: nginx\n          name: web\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n\n"
  },
  {
    "path": "script/test/fixtures/namespace/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\n  namespace: web\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: web\n\n---\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: web\n  namespace: web\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\n  namespace: web\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: web\n  template:\n    metadata:\n      labels:\n        io.kompose.service: web\n    spec:\n      containers:\n        - image: ' '\n          name: web\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - web\n        from:\n          kind: ImageStreamTag\n          name: web:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: web\n  name: web\n  namespace: web\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/network/compose-v3.yaml",
    "content": "networks:\n  app:\n    external:\n      name: app-network\n  web:\n    external:\n      name: web-network\nservices:\n  appFoo:\n    image: foo:latest\n    command: sh -c \"echo Hello Foo\"\n    networks:\n      app: {}\n      web: {}\n"
  },
  {
    "path": "script/test/fixtures/network/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"appfoo\"\n        },\n        \"name\": \"appfoo\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"appfoo\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.network/app-network\": \"true\",\n              \"io.kompose.network/web-network\": \"true\",\n              \"io.kompose.service\": \"appfoo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"args\": [\n                  \"sh\",\n                  \"-c\",\n                  \"echo Hello Foo\"\n                ],\n                \"image\": \"foo:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"appfoo\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"app-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/app-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/app-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/web-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/web-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/network/output-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"appfoo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"appfoo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"appfoo\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"appfoo:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"appfoo\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.network/app-network\": \"true\",\n              \"io.kompose.network/web-network\": \"true\",\n              \"io.kompose.service\": \"appfoo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"appfoo\",\n                \"image\": \" \",\n                \"args\": [\n                  \"sh\",\n                  \"-c\",\n                  \"echo Hello Foo\"\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"appfoo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"appfoo\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"foo:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/network-mode-service/compose.yaml",
    "content": "\nservices:\n  client:\n    image: busybox\n    command: ['sleep', 'infinity']\n    container_name: threats-client\n    restart: unless-stopped\n    ports:\n      - '8080:8080'\n\n  server:\n    image: busybox\n    command: ['sleep', 'infinity']\n    container_name: threats-server\n    restart: unless-stopped\n    network_mode: service:client"
  },
  {
    "path": "script/test/fixtures/network-mode-service/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: client\n  name: client\nspec:\n  ports:\n    - name: \"8080\"\n      port: 8080\n      targetPort: 8080\n  selector:\n    io.kompose.service: client\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: client\n  name: client\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: client\n  template:\n    metadata:\n      labels:\n        io.kompose.service: client\n    spec:\n      containers:\n        - args:\n            - sleep\n            - infinity\n          image: busybox\n          name: threats-client\n          ports:\n            - containerPort: 8080\n              protocol: TCP\n        - args:\n            - sleep\n            - infinity\n          image: busybox\n          name: threats-server\n      restartPolicy: Always\n"
  },
  {
    "path": "script/test/fixtures/network-policies/compose.yaml",
    "content": "\nnetworks:\n  web:\n\nservices:\n  nginx:\n    image: nginx\n    ports:\n      - 80:80\n    networks:\n    - web\n"
  },
  {
    "path": "script/test/fixtures/network-policies/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: nginx\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: nginx\n  template:\n    metadata:\n      labels:\n        io.kompose.network/network-policies-web: \"true\"\n        io.kompose.service: nginx\n    spec:\n      containers:\n        - image: nginx\n          name: nginx\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n\n---\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: network-policies-web\nspec:\n  ingress:\n    - from:\n        - podSelector:\n            matchLabels:\n              io.kompose.network/network-policies-web: \"true\"\n  podSelector:\n    matchLabels:\n      io.kompose.network/network-policies-web: \"true\"\n\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/README.md",
    "content": "### Usage\n\nRef: http://anandmanisankar.com/posts/docker-container-nginx-node-redis-example/\n\n```bash\ndocker-compose up\n```\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/compose-v3.yaml",
    "content": "\nservices:\n  nginx:\n      build: ./nginx\n      ports:\n          - \"80:80\"\n      restart: always\n\n  node1:\n      build: ./node\n      ports:\n          - \"8080\"\n  node2:\n      build: ./node\n      ports:\n          - \"8080\"\n  node3:\n      build: ./node\n      ports:\n          - \"8080\"\n  redis:\n      image: redis\n      ports:\n          - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/compose.yaml",
    "content": "\nservices:\n  nginx:\n      build: ./nginx\n      ports:\n          - \"80:80\"\n      restart: always\n\n  node1:\n      build: ./node\n      ports:\n          - \"8080\"\n  node2:\n      build: ./node\n      ports:\n          - \"8080\"\n  node3:\n      build: ./node\n      ports:\n          - \"8080\"\n  redis:\n      image: redis\n      ports:\n          - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/nginx/Dockerfile",
    "content": "# Set nginx base image\nFROM nginx\n\n# File Author / Maintainer\nMAINTAINER Anand Mani Sankar\n\n# Copy custom configuration file from the current directory\nCOPY nginx.conf /etc/nginx/nginx.conf\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/nginx/nginx.conf",
    "content": "worker_processes 4;\n\nevents { worker_connections 1024; }\n\nhttp {\n\n\tupstream node-app {\n\t      least_conn;\n\t      server node1:8080 weight=60 max_fails=10 fail_timeout=60s;\n\t      server node2:8080 weight=60 max_fails=10 fail_timeout=60s;\n\t      server node3:8080 weight=60 max_fails=10 fail_timeout=60s;\n\t}\n\t \n\tserver {\n\t      listen 80;\n\t \n\t      location / {\n\t        proxy_pass http://node-app;\n\t        proxy_http_version 1.1;\n\t        proxy_set_header Upgrade $http_upgrade;\n\t        proxy_set_header Connection 'upgrade';\n\t        proxy_set_header Host $host;\n\t        proxy_cache_bypass $http_upgrade;\n\t      }\n\t}\n}\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/node/Dockerfile",
    "content": "FROM centos:7\n\nRUN yum -y install epel-release && yum install -y nodejs npm gcc* make \nRUN /bin/bash -c 'npm install -g nodemon' && mkdir /src\n\n# Define working directory\nWORKDIR /src\nADD . /src\n\nRUN cd /src && npm install\n\n# Expose port\nEXPOSE  8080\n\n# Run app using nodemon\nCMD /bin/bash -c 'nodemon /src/index.js'\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/node/index.js",
    "content": "var express = require('express'),\n    http = require('http'),\n    redis = require('redis');\n\nvar app = express();\n\nconsole.log(process.env.REDIS_PORT_6379_TCP_ADDR + ':' + process.env.REDIS_PORT_6379_TCP_PORT);\n\n// APPROACH 1: Using environment variables created by Docker\n// var client = redis.createClient(\n// \tprocess.env.REDIS_PORT_6379_TCP_PORT,\n//   \tprocess.env.REDIS_PORT_6379_TCP_ADDR\n// );\n\n// APPROACH 2: Using host entries created by Docker in /etc/hosts (RECOMMENDED)\nvar client = redis.createClient('6379', 'redis');\n\n\napp.get('/', function(req, res, next) {\n  client.incr('counter', function(err, counter) {\n    if(err) return next(err);\n    res.send('This page has been viewed ' + counter + ' times!');\n  });\n});\n\nhttp.createServer(app).listen(process.env.PORT || 8080, function() {\n  console.log('Listening on port ' + (process.env.PORT || 8080));\n});"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/node/package.json",
    "content": "{\n  \"name\": \"node\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"author\": \"Anand Mani Sankar\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"express\": \"^4.12.3\",\n    \"hiredis\": \"^0.2.0\",\n    \"mocha\": \"^2.2.1\",\n    \"redis\": \"^0.12.1\"\n  }\n}\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/node/test/dummyTest.js",
    "content": "var assert = require(\"assert\");\r\n\r\ndescribe('Dummy Test', function(){\r\n    it('should pass', function(){\r\n      assert.ok(true, \"It is true!\");\r\n    });\r\n});"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/output-k8s-template-v3.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"name\": \"nginx\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"nginx\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"name\": \"node1\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"node1\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"node1\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"node1\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"name\": \"node2\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"node2\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node2\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"node2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"node2\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"name\": \"node3\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"node3\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node3\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"node3\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"node3\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"name\": \"nginx\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"nginx\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"name\": \"node1\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"node1\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"node1\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"node1\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"name\": \"node2\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"node2\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node2\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"node2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"node2\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"name\": \"node3\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"node3\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node3\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"node3\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"node3\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/output-os-template-v3.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"nginx\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"nginx:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"nginx\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"nginx\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/nginx/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"nginx:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node1\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node1:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node1\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node1\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/node/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"node1:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node2\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node2:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node2\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node2\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node2\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/node/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"node2:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node3\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node3:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node3\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node3\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node3\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/node/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"node3:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {},\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"nginx\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"nginx:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"nginx\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"nginx\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/nginx/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"nginx:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node1\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node1:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node1\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node1\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/node/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"node1:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node2\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node2:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node2\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node2\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node2\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/node/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"node2:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node3\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node3:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node3\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node3\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node3\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"BuildConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          }\n        ],\n        \"runPolicy\": \"Serial\",\n        \"source\": {\n          \"type\": \"Git\",\n          \"git\": {\n            \"uri\": \"%URI%\",\n            \"ref\": \"%REF%\"\n          },\n          \"contextDir\": \"script/test/fixtures/nginx-node-redis/node/\"\n        },\n        \"strategy\": {\n          \"type\": \"Docker\",\n          \"dockerStrategy\": {}\n        },\n        \"output\": {\n          \"to\": {\n            \"kind\": \"ImageStreamTag\",\n            \"name\": \"node3:latest\"\n          }\n        },\n        \"resources\": {},\n        \"postCommit\": {},\n        \"affinity\": null\n      },\n      \"status\": {\n        \"lastVersion\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {},\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/nginx-node-redis/output-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"8080\",\n            \"port\": 8080,\n            \"targetPort\": 8080\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"nginx\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"nginx:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"nginx\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"nginx\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node1\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node1:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node1\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node1\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node1\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node1\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node1\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node2\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node2:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node2\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node2\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node2\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node2\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node2\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"node3\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"node3:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"node3\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"node3\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"node3\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 8080\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"node3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"node3\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"node3\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/no-profile-warning/compose.yaml",
    "content": "services:\n  web:\n    image: nginx\n    profiles:\n      - test\n    ports:\n      - 80:80\n"
  },
  {
    "path": "script/test/fixtures/ports-with-ip/docker-compose.yml",
    "content": "\nservices:\n    web:\n      image: tuna/docker-counter23\n      ports:\n        - \"127.0.0.1:5000:5000/tcp\"\n      links:\n        - redis\n      networks:\n        - default\n    \n    redis:\n      image: redis:3.0\n      networks: \n        - default\n      ports:\n        - \"6379/tcp\"\n        - \"1234:1235/udp\"\n"
  },
  {
    "path": "script/test/fixtures/ports-with-ip/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          },\n          {\n            \"name\": \"1234\",\n            \"protocol\": \"UDP\",\n            \"port\": 1234,\n            \"targetPort\": 1235\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  },\n                  {\n                    \"containerPort\": 1235,\n                    \"protocol\": \"UDP\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000,\n                    \"hostIP\": \"127.0.0.1\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/ports-with-ip/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"1.0.0 (HEAD)\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          },\n          {\n            \"name\": \"1234\",\n            \"protocol\": \"UDP\",\n            \"port\": 1234,\n            \"targetPort\": 1235\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"1.0.0 (HEAD)\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"1.0.0 (HEAD)\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \"redis:3.0\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  },\n                  {\n                    \"containerPort\": 1235,\n                    \"protocol\": \"UDP\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {}\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"1.0.0 (HEAD)\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \"tuna/docker-counter23\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000,\n                    \"hostIP\": \"127.0.0.1\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {}\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/pvc-request-size/compose.yaml",
    "content": "\nservices:\n  redis:\n    restart: always\n    image: sameersbn/redis:latest\n    command:\n      - --loglevel warning\n    volumes:\n      - /srv/docker/gitlab/redis:/var/lib/redis\n    ports:\n      - \"6379\"\n\n  postgresql:\n    restart: always\n    image: sameersbn/postgresql:9.5-3\n    volumes:\n      - /srv/docker/gitlab/postgresql:/var/lib/postgresql\n    environment:\n      - DB_USER=gitlab\n      - DB_PASS=password\n      - DB_NAME=gitlabhq_production\n      - DB_EXTENSION=pg_trgm\n    ports:\n      - \"5432\"\n    labels:\n      kompose.volume.size: 200Mi\n"
  },
  {
    "path": "script/test/fixtures/pvc-request-size/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"200Mi\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"200Mi\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"postgresql\"\n          }\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"postgresql\"\n            },\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\",\n              \"kompose.volume.size\": \"200Mi\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"postgresql-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"postgresql-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"postgresql\",\n                \"image\": \"sameersbn/postgresql:9.5-3\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_EXTENSION\",\n                    \"value\": \"pg_trgm\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlabhq_production\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"postgresql-claim0\",\n                    \"mountPath\": \"/var/lib/postgresql\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"200Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            },\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"redis-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"redis-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \"sameersbn/redis:latest\",\n                \"args\": [\n                  \"--loglevel warning\"\n                ],\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"redis-claim0\",\n                    \"mountPath\": \"/var/lib/redis\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"300Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/pvc-request-size/output-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.volume.size\": \"200Mi\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"annotations\": {\n          \"kompose.volume.size\": \"200Mi\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"postgresql\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"postgresql:9.5-3\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"postgresql\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"postgresql\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"postgresql-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"postgresql-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"postgresql\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"DB_EXTENSION\",\n                    \"value\": \"pg_trgm\"\n                  },\n                  {\n                    \"name\": \"DB_NAME\",\n                    \"value\": \"gitlabhq_production\"\n                  },\n                  {\n                    \"name\": \"DB_PASS\",\n                    \"value\": \"password\"\n                  },\n                  {\n                    \"name\": \"DB_USER\",\n                    \"value\": \"gitlab\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"postgresql-claim0\",\n                    \"mountPath\": \"/var/lib/postgresql\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {\n        \"latestVersion\": 0,\n        \"observedGeneration\": 0,\n        \"replicas\": 0,\n        \"updatedReplicas\": 0,\n        \"availableReplicas\": 0,\n        \"unavailableReplicas\": 0\n      }\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql\"\n        }\n      },\n      \"spec\": {\n        \"lookupPolicy\": {\n          \"local\": false\n        },\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"sameersbn/postgresql:9.5-3\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {},\n            \"referencePolicy\": {\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"postgresql-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"postgresql-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"200Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"redis-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"redis-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"args\": [\n                  \"--loglevel warning\"\n                ],\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"redis-claim0\",\n                    \"mountPath\": \"/var/lib/redis\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {\n        \"latestVersion\": 0,\n        \"observedGeneration\": 0,\n        \"replicas\": 0,\n        \"updatedReplicas\": 0,\n        \"availableReplicas\": 0,\n        \"unavailableReplicas\": 0\n      }\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"lookupPolicy\": {\n          \"local\": false\n        },\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"sameersbn/redis:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {},\n            \"referencePolicy\": {\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"300Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/read-only/compose.yaml",
    "content": "services:\n  test:\n    image: alpine\n    read_only: true\n    ports:\n    - 80:80\n"
  },
  {
    "path": "script/test/fixtures/read-only/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: test\n  name: test\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: test\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: test\n  name: test\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: test\n  template:\n    metadata:\n      labels:\n        io.kompose.service: test\n    spec:\n      containers:\n        - image: alpine\n          name: test\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          securityContext:\n            readOnlyRootFilesystem: true\n      restartPolicy: Always\n\n\n"
  },
  {
    "path": "script/test/fixtures/read-only/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: test\n  name: test\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: test\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: test\n  name: test\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: test\n  template:\n    metadata:\n      labels:\n        io.kompose.service: test\n    spec:\n      containers:\n        - image: ' '\n          name: test\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          securityContext:\n            readOnlyRootFilesystem: true\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - test\n        from:\n          kind: ImageStreamTag\n          name: test:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: test\n  name: test\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: alpine\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/redis-example/compose.yaml",
    "content": "services:\n  web:\n    image: tuna/docker-counter23\n    ports:\n      - \"5000:5000\"\n    links:\n      - redis\n  redis:\n    image: redis:3.0\n    ports:\n      - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/resources-lowercase/compose.yaml",
    "content": "services:\n  NGINX:\n    image: nginx:latest\n    ports:\n    - 80:80\n"
  },
  {
    "path": "script/test/fixtures/resources-lowercase/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: nginx\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: nginx\n  template:\n    metadata:\n      labels:\n        io.kompose.service: nginx\n    spec:\n      containers:\n        - image: nginx:latest\n          name: nginx\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/resources-lowercase/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: nginx\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: nginx\n  template:\n    metadata:\n      labels:\n        io.kompose.service: nginx\n    spec:\n      containers:\n        - image: ' '\n          name: nginx\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - nginx\n        from:\n          kind: ImageStreamTag\n          name: nginx:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: nginx\n  name: nginx\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx:latest\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/secrets/docker-compose-secrets-long.yml",
    "content": "services:\n  redis:\n    image: redis:latest\n    deploy:\n      replicas: 1\n    secrets:\n      - source: my_secret\n        target: redis_secret\n        uid: '103'\n        gid: '103'\n        mode: 0440\nsecrets:\n  my_secret:\n    file: ./my_secret.txt\n  my_other_secret:\n    external: true"
  },
  {
    "path": "script/test/fixtures/secrets/docker-compose-secrets-short.yml",
    "content": "services:\n  redis:\n    image: redis:latest\n    deploy:\n      replicas: 1\n    secrets:\n      - my_secret\n      - my_other_secret\nsecrets:\n  my_secret:\n    file: ./my_secret.txt\n  my_other_secret:\n    external: true"
  },
  {
    "path": "script/test/fixtures/secrets/my_secret.txt",
    "content": "For the Watch!"
  },
  {
    "path": "script/test/fixtures/secrets/output-long-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Secret\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my_secret\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"my_secret\"\n        }\n      },\n      \"data\": {\n        \"my_secret\": \"Rm9yIHRoZSBXYXRjaCE=\"\n      },\n      \"type\": \"Opaque\"\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/run/secrets/my_secret\",\n                    \"name\": \"my_secret\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"my_secret\",\n                \"secret\": {\n                  \"defaultMode\": 288,\n                  \"items\": [\n                    {\n                      \"key\": \"my_secret\",\n                      \"path\": \"redis_secret\"\n                    }\n                  ],\n                  \"secretName\": \"my_secret\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/secrets/output-long-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Secret\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my_secret\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"my_secret\"\n        }\n      },\n      \"data\": {\n        \"my_secret\": \"Rm9yIHRoZSBXYXRjaCE=\"\n      },\n      \"type\": \"Opaque\"\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"my_secret\",\n                \"secret\": {\n                  \"secretName\": \"my_secret\",\n                  \"items\": [\n                    {\n                      \"key\": \"my_secret\",\n                      \"path\": \"redis_secret\"\n                    }\n                  ],\n                  \"defaultMode\": 288\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"my_secret\",\n                    \"mountPath\": \"/run/secrets/my_secret\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/secrets/output-short-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Secret\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my_secret\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"my_secret\"\n        }\n      },\n      \"data\": {\n        \"my_secret\": \"Rm9yIHRoZSBXYXRjaCE=\"\n      },\n      \"type\": \"Opaque\"\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/run/secrets/my_secret\",\n                    \"name\": \"my_secret\"\n                  },\n                  {\n                    \"mountPath\": \"/run/secrets/my_other_secret\",\n                    \"name\": \"my_other_secret\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"my_secret\",\n                \"secret\": {\n                  \"items\": [\n                    {\n                      \"key\": \"my_secret\",\n                      \"path\": \"my_secret\"\n                    }\n                  ],\n                  \"secretName\": \"my_secret\"\n                }\n              },\n              {\n                \"name\": \"my_other_secret\",\n                \"secret\": {\n                  \"items\": [\n                    {\n                      \"key\": \"my_other_secret\",\n                      \"path\": \"my_other_secret\"\n                    }\n                  ],\n                  \"secretName\": \"my_other_secret\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/secrets/output-short-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Secret\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"my_secret\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"my_secret\"\n        }\n      },\n      \"data\": {\n        \"my_secret\": \"Rm9yIHRoZSBXYXRjaCE=\"\n      },\n      \"type\": \"Opaque\"\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"my_secret\",\n                \"secret\": {\n                  \"secretName\": \"my_secret\",\n                  \"items\": [\n                    {\n                      \"key\": \"my_secret\",\n                      \"path\": \"my_secret\"\n                    }\n                  ]\n                }\n              },\n              {\n                \"name\": \"my_other_secret\",\n                \"secret\": {\n                  \"secretName\": \"my_other_secret\",\n                  \"items\": [\n                    {\n                      \"key\": \"my_other_secret\",\n                      \"path\": \"my_other_secret\"\n                    }\n                  ]\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"my_secret\",\n                    \"mountPath\": \"/run/secrets/my_secret\"\n                  },\n                  {\n                    \"name\": \"my_other_secret\",\n                    \"mountPath\": \"/run/secrets/my_other_secret\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/security-contexts/compose.yaml",
    "content": "services:\n  dind:\n    container_name: dind\n    image: docker:28.1.1-dind\n    labels:\n      kompose.service.group: cup\n    ports:\n      - 2375:2375\n    privileged: True\n  cup:\n    container_name: cup\n    depends_on:\n      - dind\n    image: ghcr.io/sergi0g/cup:v3.4.0\n    labels:\n      kompose.service.group: cup\n    ports:\n      - 8000:8000"
  },
  {
    "path": "script/test/fixtures/security-contexts/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: cup\n  name: cup\nspec:\n  ports:\n    - name: \"8000\"\n      port: 8000\n      targetPort: 8000\n  selector:\n    io.kompose.service: cup\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: cup\n  name: dind\nspec:\n  ports:\n    - name: \"2375\"\n      port: 2375\n      targetPort: 2375\n  selector:\n    io.kompose.service: cup\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: cup\n  name: cup\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: cup\n  template:\n    metadata:\n      labels:\n        io.kompose.service: cup\n    spec:\n      containers:\n        - image: ghcr.io/sergi0g/cup:v3.4.0\n          name: cup\n          ports:\n            - containerPort: 8000\n              protocol: TCP\n        - image: docker:28.1.1-dind\n          name: dind\n          ports:\n            - containerPort: 2375\n              protocol: TCP\n          securityContext:\n            privileged: true\n      restartPolicy: Always\n"
  },
  {
    "path": "script/test/fixtures/service-group/compose.yaml",
    "content": "\nservices:\n  librenms:\n    image: librenms/librenms:latest\n    container_name: librenms\n    hostname: librenms\n    ports:\n      - target: 8000\n        published: 8000\n        protocol: tcp\n    volumes:\n      - \"./librenms:/data\"\n    environment:\n      - \"TZ=${TZ}\"\n    restart: always\n\n  dispatcher:\n    image: librenms/dispatcher:latest\n    container_name: dispatcher\n    hostname: dispatcher\n    depends_on:\n      - librenms\n    volumes:\n      - \"./librenms:/data\"\n    environment:\n      - \"TZ=${TZ}\"\n    restart: always"
  },
  {
    "path": "script/test/fixtures/service-group/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: librenms-dispatcher\n  name: librenms\nspec:\n  ports:\n    - name: \"8000\"\n      port: 8000\n      targetPort: 8000\n  selector:\n    io.kompose.service: librenms-dispatcher\n\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: librenms-dispatcher\n  name: librenms-dispatcher\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: librenms-dispatcher\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: librenms-dispatcher\n    spec:\n      containers:\n        - env:\n            - name: TZ\n          image: librenms/dispatcher:latest\n          name: dispatcher\n          volumeMounts:\n            - mountPath: /data\n              name: librenms-dispatcher-claim0\n        - env:\n            - name: TZ\n          image: librenms/librenms:latest\n          name: librenms\n          ports:\n            - containerPort: 8000\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /data\n              name: librenms-dispatcher-claim0\n      hostname: librenms\n      restartPolicy: Always\n      volumes:\n        - name: librenms-dispatcher-claim0\n          persistentVolumeClaim:\n            claimName: librenms-dispatcher-claim0\n\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: librenms-dispatcher-claim0\n  name: librenms-dispatcher-claim0\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n\n"
  },
  {
    "path": "script/test/fixtures/service-label/docker-compose.yaml",
    "content": "services:\n  mariadb:\n    ports:\n      - '3306:3306'\n    labels:\n      kompose.service.type: nodeport\n      kompose.service.nodeport.port: \"33111\"\n    image: 'bitnami/mariadb:latest'\n    environment:\n      - MARIADB_USER=bn_wordpress\n      - MARIADB_DATABASE=bitnami_wordpress\n      - ALLOW_EMPTY_PASSWORD=yes\n"
  },
  {
    "path": "script/test/fixtures/service-label/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.nodeport.port\": \"33111\",\n          \"kompose.service.type\": \"nodeport\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3306\",\n            \"port\": 3306,\n            \"targetPort\": 3306,\n            \"nodePort\": 33111\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.nodeport.port\": \"33111\",\n          \"kompose.service.type\": \"nodeport\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"name\": \"mariadb\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"mariadb\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.nodeport.port\": \"33111\",\n              \"kompose.service.type\": \"nodeport\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mariadb\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"value\": \"yes\"\n                  },\n                  {\n                    \"name\": \"MARIADB_DATABASE\",\n                    \"value\": \"bitnami_wordpress\"\n                  },\n                  {\n                    \"name\": \"MARIADB_USER\",\n                    \"value\": \"bn_wordpress\"\n                  }\n                ],\n                \"image\": \"bitnami/mariadb:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"mariadb\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3306\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/service-label/output-oc.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.nodeport.port\": \"33111\",\n          \"kompose.service.type\": \"nodeport\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3306\",\n            \"port\": 3306,\n            \"targetPort\": 3306,\n            \"nodePort\": 33111\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"type\": \"NodePort\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.nodeport.port\": \"33111\",\n          \"kompose.service.type\": \"nodeport\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"mariadb\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"mariadb:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mariadb\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"mariadb\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3306\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"value\": \"yes\"\n                  },\n                  {\n                    \"name\": \"MARIADB_DATABASE\",\n                    \"value\": \"bitnami_wordpress\"\n                  },\n                  {\n                    \"name\": \"MARIADB_USER\",\n                    \"value\": \"bn_wordpress\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"bitnami/mariadb:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/service-name-change/docker-compose.yml",
    "content": "services:\n  mariadb:\n    labels:\n      kompose.service.type: headless\n    image: 'bitnami/mariadb:latest'\n    volumes:\n      - 'mariadb-data:/bitnami/mariadb'\n    environment:\n      - MARIADB_USER=bn_wordpress\n      - MARIADB_DATABASE=bitnami_wordpress\n      - ALLOW_EMPTY_PASSWORD=yes\n  wordpress:\n    image: 'bitnami/wordpress:latest'\n    ports:\n      - '80:80'\n      - '443:443'\n    volumes:\n      - 'wordpress-data:/bitnami/wordpress'\n      - 'apache-data:/bitnami/apache'\n      - 'php-data:/bitnami/php'\n    depends_on:\n      - mariadb\n    environment:\n      - MARIADB_HOST=mariadb\n      - MARIADB_PORT=3306\n      - WORDPRESS_DATABASE_USER=bn_wordpress\n      - WORDPRESS_DATABASE_NAME=bitnami_wordpress\n      - ALLOW_EMPTY_PASSWORD=yes\nvolumes:\n  mariadb-data:\n    driver: local\n  wordpress-data:\n    driver: local\n  apache-data:\n    driver: local\n  php-data:\n    driver: local\n"
  },
  {
    "path": "script/test/fixtures/service-name-change/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"443\",\n            \"port\": 443,\n            \"targetPort\": 443\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"name\": \"mariadb\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"mariadb\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mariadb\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"value\": \"yes\"\n                  },\n                  {\n                    \"name\": \"MARIADB_DATABASE\",\n                    \"value\": \"bitnami_wordpress\"\n                  },\n                  {\n                    \"name\": \"MARIADB_USER\",\n                    \"value\": \"bn_wordpress\"\n                  }\n                ],\n                \"image\": \"bitnami/mariadb:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"mariadb\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/bitnami/mariadb\",\n                    \"name\": \"servicenamechange-mariadb-data\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"servicenamechange-mariadb-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-mariadb-data\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-mariadb-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-mariadb-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"name\": \"wordpress\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"wordpress\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"wordpress\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"value\": \"yes\"\n                  },\n                  {\n                    \"name\": \"MARIADB_HOST\",\n                    \"value\": \"mariadb\"\n                  },\n                  {\n                    \"name\": \"MARIADB_PORT\",\n                    \"value\": \"3306\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_DATABASE_NAME\",\n                    \"value\": \"bitnami_wordpress\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_DATABASE_USER\",\n                    \"value\": \"bn_wordpress\"\n                  }\n                ],\n                \"image\": \"bitnami/wordpress:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"wordpress\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 443\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/bitnami/wordpress\",\n                    \"name\": \"servicenamechange-wordpress-data\"\n                  },\n                  {\n                    \"mountPath\": \"/bitnami/apache\",\n                    \"name\": \"servicenamechange-apache-data\"\n                  },\n                  {\n                    \"mountPath\": \"/bitnami/php\",\n                    \"name\": \"servicenamechange-php-data\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"servicenamechange-wordpress-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-wordpress-data\"\n                }\n              },\n              {\n                \"name\": \"servicenamechange-apache-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-apache-data\"\n                }\n              },\n              {\n                \"name\": \"servicenamechange-php-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-php-data\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-wordpress-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-wordpress-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-apache-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-apache-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-php-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-php-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/service-name-change/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"443\",\n            \"port\": 443,\n            \"targetPort\": 443\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"mariadb\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"mariadb:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"mariadb\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"mariadb\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"servicenamechange-mariadb-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-mariadb-data\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"mariadb\",\n                \"image\": \" \",\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"value\": \"yes\"\n                  },\n                  {\n                    \"name\": \"MARIADB_DATABASE\",\n                    \"value\": \"bitnami_wordpress\"\n                  },\n                  {\n                    \"name\": \"MARIADB_USER\",\n                    \"value\": \"bn_wordpress\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"servicenamechange-mariadb-data\",\n                    \"mountPath\": \"/bitnami/mariadb\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"mariadb\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"mariadb\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"bitnami/mariadb:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-mariadb-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-mariadb-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"wordpress\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"wordpress:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"wordpress\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"wordpress\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"servicenamechange-wordpress-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-wordpress-data\"\n                }\n              },\n              {\n                \"name\": \"servicenamechange-apache-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-apache-data\"\n                }\n              },\n              {\n                \"name\": \"servicenamechange-php-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"servicenamechange-php-data\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"wordpress\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 443\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"ALLOW_EMPTY_PASSWORD\",\n                    \"value\": \"yes\"\n                  },\n                  {\n                    \"name\": \"MARIADB_HOST\",\n                    \"value\": \"mariadb\"\n                  },\n                  {\n                    \"name\": \"MARIADB_PORT\",\n                    \"value\": \"3306\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_DATABASE_NAME\",\n                    \"value\": \"bitnami_wordpress\"\n                  },\n                  {\n                    \"name\": \"WORDPRESS_DATABASE_USER\",\n                    \"value\": \"bn_wordpress\"\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"servicenamechange-wordpress-data\",\n                    \"mountPath\": \"/bitnami/wordpress\"\n                  },\n                  {\n                    \"name\": \"servicenamechange-apache-data\",\n                    \"mountPath\": \"/bitnami/apache\"\n                  },\n                  {\n                    \"name\": \"servicenamechange-php-data\",\n                    \"mountPath\": \"/bitnami/php\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"wordpress\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"wordpress\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"bitnami/wordpress:latest\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-wordpress-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-wordpress-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-apache-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-apache-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"servicenamechange-php-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"servicenamechange-php-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/single-file-output/compose.yaml",
    "content": "\nservices:\n  front_end:\n    image: gcr.io/google-samples/gb-frontend:v4\n    ports:\n      - \"80:80\"\n    environment:\n      - GET_HOSTS_FROM=dns\n    labels:\n      kompose.service.expose: lb\n      kompose.service.expose.ingress-class-name: nginx\n"
  },
  {
    "path": "script/test/fixtures/single-file-output/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front_end\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: front-end\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: front-end\n  template:\n    metadata:\n      labels:\n        io.kompose.service: front-end\n    spec:\n      containers:\n        - env:\n            - name: GET_HOSTS_FROM\n              value: dns\n          image: gcr.io/google-samples/gb-frontend:v4\n          name: front-end\n          ports:\n            - containerPort: 80\n              protocol: TCP\n      restartPolicy: Always\n\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  labels:\n    io.kompose.service: front-end\n  name: front-end\nspec:\n  ingressClassName: nginx\n  rules:\n    - host: lb\n      http:\n        paths:\n          - backend:\n              service:\n                name: front-end\n                port:\n                  number: 80\n            path: /\n            pathType: Prefix\n\n"
  },
  {
    "path": "script/test/fixtures/statefulset/compose.yaml",
    "content": "    \nservices:\n  db:\n    image: mysql:5.7\n    volumes:\n      - db_data:/var/lib/mysql\n    restart: always\n    environment:\n      MYSQL_ROOT_PASSWORD: somewordpress\n      MYSQL_DATABASE: wordpress\n      MYSQL_USER: wordpress\n      MYSQL_PASSWORD: wordpress\n    ports:\n      - \"3306:3306\"\n    \n  wordpress:\n    depends_on:\n      - db\n    image: wordpress:latest\n    volumes:\n      - wordpress_data:/var/www/html\n    ports:\n      - \"8000:80\"\n    restart: always\n    environment:\n      WORDPRESS_DB_HOST: db:3306\n      WORDPRESS_DB_USER: wordpress\n      WORDPRESS_DB_PASSWORD: wordpress\n      WORDPRESS_DB_NAME: wordpress\nvolumes:\n  db_data: {}\n  wordpress_data: {}"
  },
  {
    "path": "script/test/fixtures/statefulset/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  clusterIP: None\n  ports:\n    - name: \"3306\"\n      port: 3306\n      targetPort: 3306\n  selector:\n    io.kompose.service: db\n  type: ClusterIP\n\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: wordpress\n  name: wordpress\nspec:\n  clusterIP: None\n  ports:\n    - name: \"8000\"\n      port: 8000\n      targetPort: 80\n  selector:\n    io.kompose.service: wordpress\n  type: ClusterIP\n\n\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: db\n  serviceName: db\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - env:\n            - name: MYSQL_DATABASE\n              value: wordpress\n            - name: MYSQL_PASSWORD\n              value: wordpress\n            - name: MYSQL_ROOT_PASSWORD\n              value: somewordpress\n            - name: MYSQL_USER\n              value: wordpress\n          image: mysql:5.7\n          name: db\n          ports:\n            - containerPort: 3306\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /var/lib/mysql\n              name: db-data\n      restartPolicy: Always\n  volumeClaimTemplates:\n    - metadata:\n        labels:\n          io.kompose.service: db-data\n        name: db-data\n      spec:\n        accessModes:\n          - ReadWriteOnce\n        resources:\n          requests:\n            storage: 100Mi\n\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  labels:\n    io.kompose.service: wordpress\n  name: wordpress\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: wordpress\n  serviceName: wordpress\n  template:\n    metadata:\n      labels:\n        io.kompose.service: wordpress\n    spec:\n      containers:\n        - env:\n            - name: WORDPRESS_DB_HOST\n              value: db:3306\n            - name: WORDPRESS_DB_NAME\n              value: wordpress\n            - name: WORDPRESS_DB_PASSWORD\n              value: wordpress\n            - name: WORDPRESS_DB_USER\n              value: wordpress\n          image: wordpress:latest\n          name: wordpress\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /var/www/html\n              name: wordpress-data\n      restartPolicy: Always\n  volumeClaimTemplates:\n    - metadata:\n        labels:\n          io.kompose.service: wordpress-data\n        name: wordpress-data\n      spec:\n        accessModes:\n          - ReadWriteOnce\n        resources:\n          requests:\n            storage: 100Mi\n\n"
  },
  {
    "path": "script/test/fixtures/statefulset/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  ports:\n    - name: \"3306\"\n      port: 3306\n      targetPort: 3306\n  selector:\n    io.kompose.service: db\n\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: wordpress\n  name: wordpress\nspec:\n  ports:\n    - name: \"8000\"\n      port: 8000\n      targetPort: 80\n  selector:\n    io.kompose.service: wordpress\n\n\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: db\n  serviceName: db\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - env:\n            - name: MYSQL_DATABASE\n              value: wordpress\n            - name: MYSQL_PASSWORD\n              value: wordpress\n            - name: MYSQL_ROOT_PASSWORD\n              value: somewordpress\n            - name: MYSQL_USER\n              value: wordpress\n          image: mysql:5.7\n          name: db\n          ports:\n            - containerPort: 3306\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /var/lib/mysql\n              name: db-data\n      restartPolicy: Always\n  volumeClaimTemplates:\n    - metadata:\n        labels:\n          io.kompose.service: db-data\n        name: db-data\n      spec:\n        accessModes:\n          - ReadWriteOnce\n        resources:\n          requests:\n            storage: 100Mi\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - env:\n            - name: MYSQL_DATABASE\n              value: wordpress\n            - name: MYSQL_PASSWORD\n              value: wordpress\n            - name: MYSQL_ROOT_PASSWORD\n              value: somewordpress\n            - name: MYSQL_USER\n              value: wordpress\n          image: ' '\n          name: db\n          ports:\n            - containerPort: 3306\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /var/lib/mysql\n              name: db-data\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - db\n        from:\n          kind: ImageStreamTag\n          name: db:5.7\n      type: ImageChange\n\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: mysql:5.7\n      name: \"5.7\"\n      referencePolicy:\n        type: \"\"\n\n\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  labels:\n    io.kompose.service: wordpress\n  name: wordpress\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: wordpress\n  serviceName: wordpress\n  template:\n    metadata:\n      labels:\n        io.kompose.service: wordpress\n    spec:\n      containers:\n        - env:\n            - name: WORDPRESS_DB_HOST\n              value: db:3306\n            - name: WORDPRESS_DB_NAME\n              value: wordpress\n            - name: WORDPRESS_DB_PASSWORD\n              value: wordpress\n            - name: WORDPRESS_DB_USER\n              value: wordpress\n          image: wordpress:latest\n          name: wordpress\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /var/www/html\n              name: wordpress-data\n      restartPolicy: Always\n  volumeClaimTemplates:\n    - metadata:\n        labels:\n          io.kompose.service: wordpress-data\n        name: wordpress-data\n      spec:\n        accessModes:\n          - ReadWriteOnce\n        resources:\n          requests:\n            storage: 100Mi\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: wordpress\n  name: wordpress\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: wordpress\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: wordpress\n    spec:\n      containers:\n        - env:\n            - name: WORDPRESS_DB_HOST\n              value: db:3306\n            - name: WORDPRESS_DB_NAME\n              value: wordpress\n            - name: WORDPRESS_DB_PASSWORD\n              value: wordpress\n            - name: WORDPRESS_DB_USER\n              value: wordpress\n          image: ' '\n          name: wordpress\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          volumeMounts:\n            - mountPath: /var/www/html\n              name: wordpress-data\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - wordpress\n        from:\n          kind: ImageStreamTag\n          name: wordpress:latest\n      type: ImageChange\n\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: wordpress\n  name: wordpress\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: wordpress:latest\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n\n"
  },
  {
    "path": "script/test/fixtures/stdin/docker-compose.yaml",
    "content": "services:\n  backend:\n    image: helloworld\n"
  },
  {
    "path": "script/test/fixtures/stdin/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j -f -\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"backend\"\n        },\n        \"name\": \"backend\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"backend\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"kompose convert --stdout -j -f -\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"backend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"helloworld\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"backend\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/stdin/output.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            },\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \"redis:3.0\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {}\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/stdin-true/docker-compose.yml",
    "content": "services:\n  client:\n    image: registry.centos.org/centos/centos:7\n    ports:\n    - \"1337\"\n    stdin_open: true\n"
  },
  {
    "path": "script/test/fixtures/stdin-true/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"1337\",\n            \"port\": 1337,\n            \"targetPort\": 1337\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"name\": \"client\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"client\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"client\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.centos.org/centos/centos:7\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"client\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 1337\n                  }\n                ],\n                \"resources\": {},\n                \"stdin\": true\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/stdin-true/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"1337\",\n            \"port\": 1337,\n            \"targetPort\": 1337\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"client\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"client:7\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"client\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"client\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 1337\n                  }\n                ],\n                \"resources\": {},\n                \"stdin\": true\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"7\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.centos.org/centos/centos:7\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/storage-class-name/compose.yaml",
    "content": "services:\n  nginx:\n    image: nginx\n    ports:\n      - \"80:80\"\n    labels:\n      kompose.volume.storage-class-name: custom-storage-class-name\n    volumes:\n      - /etc/nginx/nginx.conf\n"
  },
  {
    "path": "script/test/fixtures/storage-class-name/output-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.storage-class-name\": \"custom-storage-class-name\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.storage-class-name\": \"custom-storage-class-name\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx\"\n          }\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            },\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\",\n              \"kompose.volume.storage-class-name\": \"custom-storage-class-name\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"nginx-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"nginx-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"nginx\",\n                \"image\": \"nginx\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"nginx-claim0\",\n                    \"mountPath\": \"/etc/nginx/nginx.conf\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        },\n        \"storageClassName\": \"custom-storage-class-name\"\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/storage-class-name/output-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.volume.storage-class-name\": \"custom-storage-class-name\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.volume.storage-class-name\": \"custom-storage-class-name\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"nginx\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"nginx:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"nginx-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"nginx-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"nginx\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"nginx-claim0\",\n                    \"mountPath\": \"/etc/nginx/nginx.conf\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {\n        \"latestVersion\": 0,\n        \"observedGeneration\": 0,\n        \"replicas\": 0,\n        \"updatedReplicas\": 0,\n        \"availableReplicas\": 0,\n        \"unavailableReplicas\": 0\n      }\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"lookupPolicy\": {\n          \"local\": false\n        },\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"nginx\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {},\n            \"referencePolicy\": {\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        },\n        \"storageClassName\": \"custom-storage-class-name\"\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/tty-true/docker-compose.yml",
    "content": "services:\n  client:\n    image: registry.centos.org/centos/centos:7\n    ports:\n    - \"1337\"\n    tty: true\n"
  },
  {
    "path": "script/test/fixtures/tty-true/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"1337\",\n            \"port\": 1337,\n            \"targetPort\": 1337\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"name\": \"client\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"client\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"client\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.centos.org/centos/centos:7\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"client\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 1337\n                  }\n                ],\n                \"resources\": {},\n                \"tty\": true\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/tty-true/output-oc.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider openshift -f /home/snarwade/go/src/github.com/kubernetes/kompose/script/test/fixtures/tty-true/docker-compose.yml convert --stdout -j\",\n          \"kompose.version\": \"1.0.0 (HEAD)\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"1337\",\n            \"port\": 1337,\n            \"targetPort\": 1337\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider openshift -f /home/snarwade/go/src/github.com/kubernetes/kompose/script/test/fixtures/tty-true/docker-compose.yml convert --stdout -j\",\n          \"kompose.version\": \"1.0.0 (HEAD)\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"client\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"client:7\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"client\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"client\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 1337\n                  }\n                ],\n                \"resources\": {},\n                \"tty\": true\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"7\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.centos.org/centos/centos:7\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/tty-true/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"1337\",\n            \"port\": 1337,\n            \"targetPort\": 1337\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"client\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"client:7\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"client\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"client\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"client\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 1337\n                  }\n                ],\n                \"resources\": {},\n                \"tty\": true\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"client\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"client\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"7\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.centos.org/centos/centos:7\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-hostname-multiple-ports.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n    - \"4000:4000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"batman.example.com\"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-hostname-tls.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"batman.example.com\"\n    kompose.service.expose.tls-secret: \"test-secret\"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-hostname.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"batman.example.com\"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-multiple-hostname-tls.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"batman.example.com,batwoman.example.com\"\n    kompose.service.expose.tls-secret: \"test-secret\"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-multiple-hostname.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"  batman.example.com/home ,, batwoman.example.com \"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-true-multiple-ports.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n    - \"4000:4000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"True\"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/compose-files/docker-compose-expose-true.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\n  labels:\n    kompose.service.expose: \"True\"\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-hostname-multiple-ports.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          },\n          {\n            \"name\": \"4000\",\n            \"port\": 4000,\n            \"targetPort\": 4000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"batman.example.com\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  },\n                  {\n                    \"containerPort\": 4000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"rules\": [\n          {\n            \"host\": \"batman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-hostname-tls.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.service.expose.tls-secret\": \"test-secret\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.service.expose.tls-secret\": \"test-secret\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"batman.example.com\",\n              \"kompose.service.expose.tls-secret\": \"test-secret\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.service.expose.tls-secret\": \"test-secret\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"tls\": [\n          {\n            \"hosts\": [\n              \"batman.example.com\"\n            ],\n            \"secretName\": \"test-secret\"\n          }\n        ],\n        \"rules\": [\n          {\n            \"host\": \"batman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-hostname.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"batman.example.com\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"rules\": [\n          {\n            \"host\": \"batman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-multiple-hostname-tls.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com,batwoman.example.com\",\n          \"kompose.service.expose.tls-secret\": \"test-secret\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com,batwoman.example.com\",\n          \"kompose.service.expose.tls-secret\": \"test-secret\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"batman.example.com,batwoman.example.com\",\n              \"kompose.service.expose.tls-secret\": \"test-secret\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"batman.example.com,batwoman.example.com\",\n          \"kompose.service.expose.tls-secret\": \"test-secret\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"tls\": [\n          {\n            \"hosts\": [\n              \"batman.example.com\",\n              \"batwoman.example.com\"\n            ],\n            \"secretName\": \"test-secret\"\n          }\n        ],\n        \"rules\": [\n          {\n            \"host\": \"batman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          },\n          {\n            \"host\": \"batwoman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-multiple-hostname.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"  batman.example.com/home ,, batwoman.example.com \",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"  batman.example.com/home ,, batwoman.example.com \",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"  batman.example.com/home ,, batwoman.example.com \",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"  batman.example.com/home ,, batwoman.example.com \",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"rules\": [\n          {\n            \"host\": \"batman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"path\": \"/home\",\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          },\n          {\n            \"host\": \"batwoman.example.com\",\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-true-multiple-ports.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"True\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          },\n          {\n            \"name\": \"4000\",\n            \"port\": 4000,\n            \"targetPort\": 4000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"True\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"True\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  },\n                  {\n                    \"containerPort\": 4000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"True\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"rules\": [\n          {\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/kubernetes-expose-true.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"True\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"True\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.expose\": \"True\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Ingress\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.expose\": \"True\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"rules\": [\n          {\n            \"http\": {\n              \"paths\": [\n                {\n                  \"backend\": {\n                    \"serviceName\": \"web\",\n                    \"servicePort\": 5000\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/openshift-expose-hostname-multiple-ports.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"batman.example.com\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          },\n          {\n            \"name\": \"4000\",\n            \"port\": 4000,\n            \"targetPort\": 4000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"batman.example.com\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  },\n                  {\n                    \"containerPort\": 4000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"Route\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"host\": \"batman.example.com\",\n        \"to\": {\n          \"kind\": \"Service\",\n          \"name\": \"web\",\n          \"weight\": null\n        },\n        \"port\": {\n          \"targetPort\": 5000\n        }\n      },\n      \"status\": {\n        \"ingress\": null\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/openshift-expose-hostname.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"batman.example.com\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"batman.example.com\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"Route\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"host\": \"batman.example.com\",\n        \"to\": {\n          \"kind\": \"Service\",\n          \"name\": \"web\",\n          \"weight\": null\n        },\n        \"port\": {\n          \"targetPort\": 5000\n        }\n      },\n      \"status\": {\n        \"ingress\": null\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/openshift-expose-true-multiple-ports.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"True\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          },\n          {\n            \"name\": \"4000\",\n            \"port\": 4000,\n            \"targetPort\": 4000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"True\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  },\n                  {\n                    \"containerPort\": 4000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"Route\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"host\": \"\",\n        \"to\": {\n          \"kind\": \"Service\",\n          \"name\": \"web\",\n          \"weight\": null\n        },\n        \"port\": {\n          \"targetPort\": 5000\n        }\n      },\n      \"status\": {\n        \"ingress\": null\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/expose-service/provider-files/openshift-expose-true.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"True\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.service.expose\": \"True\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"Route\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"host\": \"\",\n        \"to\": {\n          \"kind\": \"Service\",\n          \"name\": \"web\",\n          \"weight\": null\n        },\n        \"port\": {\n          \"targetPort\": 5000\n        }\n      },\n      \"status\": {\n        \"ingress\": null\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/base.yml",
    "content": "\nservices:\n  web:\n    image: richarvey/nginx-php-fpm\n    environment:\n      - ERRORS=0\n      - HIDE_NGINX_HEADERS=0\n      - REMOVE_FILES=0\n      - RUN_SCRIPTS=0\n      - PHP_ERRORS_STDERR=0\n      - ENABLE_XDEBUG=0"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/compose-new-service-prob.yml",
    "content": "\nservices:\n  server:\n    ports:\n      - 5000:5000\n  new-my-service:\n    image: nginx"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/compose-port-base.yml",
    "content": "\nservices:\n  server:\n    image: test\n    container_name: test_server\n    build:\n      context: .\n      dockerfile: Dockerfile-dev\n    ports:\n      - 3000:3000"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/compose-port-prod.yml",
    "content": "\nservices:\n  server:\n    ports:\n      - 5000:5000"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/dev.yml",
    "content": "\nservices:\n  web:\n    deploy:\n      resources:\n        limits:\n          cpus: \"1\"  # as opposed to 0.1 (default)\n        reservations:\n          cpus: \"1\"\n    environment:\n      - ERRORS=1\n      - HIDE_NGINX_HEADERS=0\n      - REMOVE_FILES=0\n      - RUN_SCRIPTS=1\n      - PHP_ERRORS_STDERR=1\n      - ENABLE_XDEBUG=1"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/first_config.txt",
    "content": "First config\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/other-toplevel-base.yml",
    "content": "\nservices:\n  other-toplevel-base:\n    image: nginx\n    volumes:\n      - firstvolume:/var/www/nginx\n    configs:\n      - source: firstconfig\n        target: /etc/nginx.conf\n        mode: 644\n\nconfigs:\n  firstconfig:\n    file: ./first_config.txt\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/other-toplevel-dev.yml",
    "content": "\nservices:\n  other-toplevel-dev:\n    image: nginx\n    volumes:\n      - firstvolume:/var/www/nginx\n    configs:\n      - source: firstconfig\n        target: /etc/nginx.conf\n        mode: 644\n\nvolumes:\n  firstvolume:\n    driver_opts:\n      type: \"nfs\"\n\nconfigs:\n  firstconfig:\n    file: ./first_config.txt\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/other-toplevel-ext.yml",
    "content": "\nservices:\n  other-toplevel-second:\n    image: nginx\n    volumes:\n      - secondvolume:/var/www/nginx\n    configs:\n      - source: secondconfig\n        target: /etc/nginx.conf\n        mode: 644\n\nvolumes:\n  secondvolume:\n    external: true\n\nconfigs:\n  secondconfig:\n    file: ./second_config.txt\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/other-toplevel-override.yml",
    "content": "\nvolumes:\n  firstvolume:\n    external: true\n\nconfigs:\n  firstconfig:\n    file: ./second_config.txt\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-base-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"ENABLE_XDEBUG\",\n                    \"value\": \"1\"\n                  },\n                  {\n                    \"name\": \"ERRORS\",\n                    \"value\": \"1\"\n                  },\n                  {\n                    \"name\": \"HIDE_NGINX_HEADERS\",\n                    \"value\": \"0\"\n                  },\n                  {\n                    \"name\": \"PHP_ERRORS_STDERR\",\n                    \"value\": \"1\"\n                  },\n                  {\n                    \"name\": \"REMOVE_FILES\",\n                    \"value\": \"0\"\n                  },\n                  {\n                    \"name\": \"RUN_SCRIPTS\",\n                    \"value\": \"1\"\n                  }\n                ],\n                \"image\": \"richarvey/nginx-php-fpm\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"resources\": {\n                  \"limits\": {\n                    \"cpu\": \"1\"\n                  },\n                  \"requests\": {\n                    \"cpu\": \"1\"\n                  }\n                }\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-compose-new-service-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"server\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"new-my-service\"\n        },\n        \"name\": \"new-my-service\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"new-my-service\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"new-my-service\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"new-my-service\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"name\": \"server\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"server\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"server\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"test\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"test-server\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3000\n                  },\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-compose-port-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"server\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"name\": \"server\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"server\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"server\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"test\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"test-server\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3000\n                  },\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-openshift-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"server\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"new-my-service\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"new-my-service\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"new-my-service\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"new-my-service:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"new-my-service\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"new-my-service\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"new-my-service\",\n                \"image\": \" \",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"new-my-service\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"new-my-service\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"nginx\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"test_server\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"server:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"server\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"test-server\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3000\n                  },\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"test\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-other-toplevel-merge-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"firstconfig\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"other-toplevel-dev\"\n        }\n      },\n      \"data\": {\n        \"first_config.txt\": \"First config\\n\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"other-toplevel-dev\"\n        },\n        \"name\": \"other-toplevel-dev\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"other-toplevel-dev\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"other-toplevel-dev\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"other-toplevel-dev\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/etc/nginx.conf\",\n                    \"name\": \"firstconfig\",\n                    \"subPath\": \"nginx.conf\"\n                  },\n                  {\n                    \"mountPath\": \"/var/www/nginx\",\n                    \"name\": \"firstvolume\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"defaultMode\": 644,\n                  \"items\": [\n                    {\n                      \"key\": \"first_config.txt\",\n                      \"path\": \"nginx.conf\"\n                    }\n                  ],\n                  \"name\": \"firstconfig\"\n                },\n                \"name\": \"firstconfig\"\n              },\n              {\n                \"name\": \"firstvolume\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"firstvolume\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"firstvolume\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"firstvolume\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"secondconfig\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"other-toplevel-second\"\n        }\n      },\n      \"data\": {\n        \"second_config.txt\": \"Second config\\n\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"other-toplevel-second\"\n        },\n        \"name\": \"other-toplevel-second\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"other-toplevel-second\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"other-toplevel-second\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"other-toplevel-second\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/etc/nginx.conf\",\n                    \"name\": \"secondconfig\",\n                    \"subPath\": \"nginx.conf\"\n                  },\n                  {\n                    \"mountPath\": \"/var/www/nginx\",\n                    \"name\": \"secondvolume\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"defaultMode\": 644,\n                  \"items\": [\n                    {\n                      \"key\": \"second_config.txt\",\n                      \"path\": \"nginx.conf\"\n                    }\n                  ],\n                  \"name\": \"secondconfig\"\n                },\n                \"name\": \"secondconfig\"\n              },\n              {\n                \"name\": \"secondvolume\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"secondvolume\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"secondvolume\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"secondvolume\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-other-toplevel-override-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"ConfigMap\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"firstconfig\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"other-toplevel-base\"\n        }\n      },\n      \"data\": {\n        \"second_config.txt\": \"Second config\\n\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"other-toplevel-base\"\n        },\n        \"name\": \"other-toplevel-base\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"other-toplevel-base\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"other-toplevel-base\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"other-toplevel-base\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/etc/nginx.conf\",\n                    \"name\": \"firstconfig\",\n                    \"subPath\": \"nginx.conf\"\n                  },\n                  {\n                    \"mountPath\": \"/var/www/nginx\",\n                    \"name\": \"firstvolume\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"configMap\": {\n                  \"defaultMode\": 644,\n                  \"items\": [\n                    {\n                      \"key\": \"second_config.txt\",\n                      \"path\": \"nginx.conf\"\n                    }\n                  ],\n                  \"name\": \"firstconfig\"\n                },\n                \"name\": \"firstconfig\"\n              },\n              {\n                \"name\": \"firstvolume\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"firstvolume\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"firstvolume\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"firstvolume\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/output-service-merge-concat-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"annotations\": {\n          \"complexlabel\": \"override\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"simplelabel.first\": \"Foo\",\n          \"simplelabel.second\": \"Bar\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"server\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"complexlabel\": \"override\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"simplelabel.first\": \"Foo\",\n          \"simplelabel.second\": \"Bar\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server\"\n        },\n        \"name\": \"server\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"server\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"complexlabel\": \"override\",\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\",\n              \"simplelabel.first\": \"Foo\",\n              \"simplelabel.second\": \"Bar\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"server\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"NEW_ONE\",\n                    \"value\": \"1234\"\n                  },\n                  {\n                    \"name\": \"SAMPLE_TO_BE_OVERRIDDEN\",\n                    \"value\": \"new\"\n                  },\n                  {\n                    \"name\": \"SIMPLE_ONE\",\n                    \"value\": \"true\"\n                  }\n                ],\n                \"image\": \"test\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"test-server\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3000\n                  },\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/simple/base/volume\",\n                    \"name\": \"server-claim0\"\n                  },\n                  {\n                    \"mountPath\": \"/common/mount/point\",\n                    \"name\": \"server-claim1\"\n                  },\n                  {\n                    \"mountPath\": \"/additional/added/volume\",\n                    \"name\": \"server-claim2\"\n                  },\n                  {\n                    \"mountPath\": \"/base-tmpdir\",\n                    \"name\": \"server-tmpfs0\"\n                  },\n                  {\n                    \"mountPath\": \"/additional-tmpdir\",\n                    \"name\": \"server-tmpfs1\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"server-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"server-claim0\"\n                }\n              },\n              {\n                \"name\": \"server-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"server-claim1\"\n                }\n              },\n              {\n                \"name\": \"server-claim2\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"server-claim2\"\n                }\n              },\n              {\n                \"emptyDir\": {\n                  \"medium\": \"Memory\"\n                },\n                \"name\": \"server-tmpfs0\"\n              },\n              {\n                \"emptyDir\": {\n                  \"medium\": \"Memory\"\n                },\n                \"name\": \"server-tmpfs1\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"server-claim2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"server-claim2\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/second_config.txt",
    "content": "Second config\n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/service-merge-concat-base.yml",
    "content": "\nservices:\n  server:\n    image: test\n    container_name: test_server\n    environment:\n      - SIMPLE_ONE=true\n      - SAMPLE_TO_BE_OVERRIDDEN=original\n    expose:\n      - \"3000\"\n    dns:\n      - 1.1.1.1\n      - 8.8.8.8\n    dns_search: first.search.domain.com\n    external_links:\n      - other_service_1\n      - common_service:alias1\n    labels:\n      - \"simplelabel.first=Foo\" \n      - \"complexlabel=original\"\n    tmpfs:\n      - /base-tmpdir\n    volumes:\n      - /simple/base/volume\n      - /base/dir:/common/mount/point\n      \n"
  },
  {
    "path": "script/test/fixtures/unused/merge-multiple-compose/service-merge-concat-override.yml",
    "content": "\nservices:\n  server:\n    image: test\n    container_name: test_server\n    environment:\n      - SAMPLE_TO_BE_OVERRIDDEN=new\n      - NEW_ONE=1234\n    expose:\n      - \"5000\"\n    dns: 9.9.9.9\n    dns_search:\n      - second.search.domain.com\n    external_links:\n      - other_service_2\n      - common_service:alias2\n    labels:\n      simplelabel.second: \"Bar\"\n      complexlabel: override\n    tmpfs: /additional-tmpdir\n    volumes:\n      - /additional/added/volume\n      - /override/dir:/common/mount/point\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-3.5.yaml",
    "content": "\nservices:\n\n  helloworld:\n    image: tutum/hello-world\n    ports:\n      - 80:80\n    expose: # this may be mis-usage, only to test expose with ports.\n      - \"3000\"\n      - \"80\"\n    networks:\n      - helloworld-network\n\nnetworks:\n  helloworld-network:\n    name: helloworld-network\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-deploy.yaml",
    "content": "services:\n  vote: # test placement and update_config\n    image: dockersamples/examplevotingapp_vote:before\n    depends_on:\n      - redis\n    deploy:\n      replicas: 2\n      placement:\n        constraints: [node.hostname == machine]\n      update_config:\n        parallelism: 2\n        delay: 10s\n        order: stop-first\n  db: # test placement\n    image: postgres\n    deploy:\n      placement:\n        constraints:\n          - node.hostname == machine\n          - engine.labels.operatingsystem == ubuntu 14.04\n          - node.labels.foo != bar\n  foo: # test labels\n    labels:\n      kompose.service.type: headless\n    deploy:\n      mode: global\n      replicas: 6\n      update_config:\n        parallelism: 2\n        delay: 10s\n        order: stop-first\n      labels:\n        com.example.description: \"This label will appear on the web service\"\n    image: redis\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-env-subs.yaml",
    "content": "services:\n  foo:\n    image: foo/bar:latest\n    environment:\n      FOO: $foo\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-env.yaml",
    "content": "services:\n  foo:\n    labels:\n      kompose.service.type: headless\n    image: foo/bar:latest\n    environment:\n      FOO: foo\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-full-example.yaml",
    "content": "\nservices:\n  foo:\n    cap_add:\n      - ALL\n\n    cap_drop:\n      - NET_ADMIN\n      - SYS_ADMIN\n\n    cgroup_parent: m-executor-abcd\n\n    # String or list\n    command: bundle exec thin -p 3000\n    # command: [\"bundle\", \"exec\", \"thin\", \"-p\", \"3000\"]\n\n    container_name: my_web-container\n\n    depends_on:\n      - db\n      - redis\n\n    deploy:\n      mode: replicated\n      replicas: 6\n      labels: [FOO=BAR]\n      update_config:\n        parallelism: 3\n        delay: 10s\n        failure_action: continue\n        monitor: 60s\n        max_failure_ratio: 0.3\n      resources:\n        limits:\n          cpus: '0.001'\n          memory: 50M\n        reservations:\n          cpus: '0.0001'\n          memory: 20M\n      restart_policy:\n        condition: on-failure\n        delay: 5s\n        max_attempts: 3\n        window: 120s\n      placement:\n        constraints: [node=foo]\n\n    devices:\n      - \"/dev/ttyUSB0:/dev/ttyUSB0\"\n\n    # String or list\n    # dns: 8.8.8.8\n    dns:\n      - 8.8.8.8\n      - 9.9.9.9\n\n    # String or list\n    # dns_search: example.com\n    dns_search:\n      - dc1.example.com\n      - dc2.example.com\n\n    domainname: foo.com\n\n    # String or list\n    # entrypoint: /code/entrypoint.sh -p 3000\n    entrypoint: [\"/code/entrypoint.sh\", \"-p\", \"3000\"]\n\n    # Items can be strings or numbers\n    expose:\n     - \"3000\"\n     - 8000\n\n    external_links:\n      - redis_1\n      - project_db_1:mysql\n      - project_db_1:postgresql\n\n    # Mapping or list\n    # Mapping values must be strings\n    # extra_hosts:\n    #   somehost: \"162.242.195.82\"\n    #   otherhost: \"50.31.209.229\"\n    extra_hosts:\n      - \"somehost:162.242.195.82\"\n      - \"otherhost:50.31.209.229\"\n\n    hostname: foo\n\n    healthcheck:\n      test: echo \"hello world\"\n      interval: 10s\n      timeout: 1s\n      retries: 5\n\n    # Any valid image reference - repo, tag, id, sha\n    image: redis\n    # image: ubuntu:14.04\n    # image: tutum/influxdb\n    # image: example-registry.com:4000/postgresql\n    # image: a4bc65fd\n    # image: busybox@sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d\n\n    ipc: host\n\n    # Mapping or list\n    # Mapping values can be strings, numbers or null\n    labels:\n      com.example.description: \"Accounting webapp\"\n      com.example.number: 42\n      com.example.empty-label:\n    # labels:\n    #   - \"com.example.description=Accounting webapp\"\n    #   - \"com.example.number=42\"\n    #   - \"com.example.empty-label\"\n\n    links:\n     - db\n     - db:database\n     - redis\n\n    logging:\n      driver: syslog\n      options:\n        syslog-address: \"tcp://192.168.0.42:123\"\n\n    mac_address: 02:42:ac:11:65:43\n\n    # network_mode: \"bridge\"\n    # network_mode: \"host\"\n    # network_mode: \"none\"\n    # Use the network mode of an arbitrary container from another service\n    # network_mode: \"service:db\"\n    # Use the network mode of another container, specified by name or id\n    # network_mode: \"container:some-container\"\n    network_mode: \"container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b\"\n\n    networks:\n      some-network:\n        aliases:\n         - alias1\n         - alias3\n      other-network:\n        ipv4_address: 172.16.238.10\n        ipv6_address: 2001:3984:3989::10\n      other-other-network:\n\n    pid: \"host\"\n\n    ports:\n      - 3000\n      - \"3000-3005\"\n      - \"8000:8000\"\n      - \"9090-9091:8080-8081\"\n      - \"49100:22\"\n      - \"127.0.0.1:8001:8001\"\n      - \"127.0.0.1:5000-5010:5000-5010\"\n\n    privileged: true\n\n    read_only: true\n\n    restart: always\n\n    security_opt:\n      - label=level:s0:c100,c200\n      - label=type:svirt_apache_t\n\n    stdin_open: true\n\n    stop_grace_period: 20s\n\n    stop_signal: SIGUSR1\n\n    # String or list\n    # tmpfs: /run\n    tmpfs:\n      - /run\n      - /tmp\n\n    tty: true\n\n    ulimits:\n      # Single number or mapping with soft + hard limits\n      nproc: 65535\n      nofile:\n        soft: 20000\n        hard: 40000\n\n    user: someone\n\n    volumes:\n      # Just specify a path and let the Engine create a volume\n      - /var/lib/mysql\n      # Specify an absolute path mapping\n      - /opt/data:/var/lib/mysql\n      # Path on the host, relative to the Compose file\n      - .:/code\n      - ./static:/var/www/html\n      # User-relative path\n      - ~/configs:/etc/configs/:ro\n      # Named volume\n      - datavolume:/var/lib/mysql\n\n    working_dir: /code\n\nnetworks:\n  # Entries can be null, which specifies simply that a network\n  # called \"{project name}_some-network\" should be created and\n  # use the default driver\n  some-network:\n\n  other-network:\n    driver: overlay\n\n    driver_opts:\n      # Values can be strings or numbers\n      foo: \"bar\"\n      baz: 1\n\n    ipam:\n      driver: overlay\n      # driver_opts:\n      #   # Values can be strings or numbers\n      #   com.docker.network.enable_ipv6: \"true\"\n      #   com.docker.network.numeric_value: 1\n      config:\n      - subnet: 172.16.238.0/24\n        # gateway: 172.16.238.1\n      - subnet: 2001:3984:3989::/64\n        # gateway: 2001:3984:3989::1\n\n  external-network:\n    # Specifies that a pre-existing network called \"external-network\"\n    # can be referred to within this file as \"external-network\"\n    external: true\n\n  other-external-network:\n    # Specifies that a pre-existing network called \"my-cool-network\"\n    # can be referred to within this file as \"other-external-network\"\n    external:\n      name: my-cool-network\n\nvolumes:\n  # Entries can be null, which specifies simply that a volume\n  # called \"{project name}_some-volume\" should be created and\n  # use the default driver\n  some-volume:\n\n  other-volume:\n    driver: flocker\n\n    driver_opts:\n      # Values can be strings or numbers\n      foo: \"bar\"\n      baz: 1\n\n  external-volume:\n    # Specifies that a pre-existing volume called \"external-volume\"\n    # can be referred to within this file as \"external-volume\"\n    external: true\n\n  other-external-volume:\n    # Specifies that a pre-existing volume called \"my-cool-volume\"\n    # can be referred to within this file as \"other-external-volume\"\n    external:\n      name: my-cool-volume\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-memcpu-partial.yaml",
    "content": "\nservices:\n  foo:\n    labels:\n      kompose.service.type: headless\n    deploy:\n      resources:\n        limits:\n          memory: 50M\n        reservations:\n          cpus: '0.001'\n    image: redis\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-memcpu.yaml",
    "content": "\nservices:\n  foo:\n    labels:\n      kompose.service.type: headless\n    deploy:\n      resources:\n        limits:\n          cpus: '0.01'\n          memory: 50M\n        reservations:\n          cpus: '0.001'\n          memory: 20M\n    image: redis\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-unset-env.yaml",
    "content": "services:\n  foo:\n    labels:\n      kompose.service.type: headless\n    image: foo/bar:latest\n    environment:\n      - BAR\n      - V3_HOST_ENV_TEST_SET_TO_BAR\n      - FOO=foo\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose-volumes.yaml",
    "content": "\nservices:\n\n  foobar:\n    labels:\n      kompose.service.type: headless\n    image: foo/bar:latest\n    volumes:\n      - /tmp/foo/bar\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/docker-compose.yaml",
    "content": "\nservices:\n\n  redis-master:\n    image: registry.k8s.io/redis:e2e \n    ports:\n      - \"6379\"\n\n  redis-replica:\n    image: registry.k8s.io/redis-slave:v2\n    ports:\n      - \"6379\"\n    environment:\n      - GET_HOSTS_FROM=dns\n\n  frontend:\n    image: gcr.io/google-samples/gb-frontend:v4\n    ports:\n      - \"80:80\"\n    environment:\n      - GET_HOSTS_FROM=dns\n    labels:\n      kompose.service.type: LoadBalancer\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/example1.env",
    "content": "# passed through\nFOO=1\n\n# overridden in example2.env\nBAR=1\n\n# overridden in full-example.yml\nBAZ=1\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/example2.env",
    "content": "BAR=2\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-deploy-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"name\": \"db\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"db\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"postgres\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"db\",\n                \"resources\": {}\n              }\n            ],\n            \"affinity\": {\n              \"nodeAffinity\": {\n                \"requiredDuringSchedulingIgnoredDuringExecution\": {\n                  \"nodeSelectorTerms\": [\n                    {\n                      \"matchExpressions\": [\n                        {\n                          \"key\": \"kubernetes.io/hostname\",\n                          \"operator\": \"In\",\n                          \"values\": [\"machine\"]\n                        },\n                        {\n                          \"key\": \"kubernetes.io/oss\",\n                          \"operator\": \"In\",\n                          \"values\": [\"ubuntu 14.04\"]\n                        },\n                        {\n                          \"key\": \"foo\",\n                          \"operator\": \"NotIn\",\n                          \"values\": [\"bar\"]\n                        }\n                      ]\n                    }\n                  ]\n                }\n              }\n            },\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"com.example.description\": \"This label will appear on the web service\",\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"name\": \"vote\"\n      },\n      \"spec\": {\n        \"replicas\": 2,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"vote\"\n          }\n        },\n        \"strategy\": {\n          \"rollingUpdate\": {\n            \"maxSurge\": 0,\n            \"maxUnavailable\": 2\n          },\n          \"type\": \"RollingUpdate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"vote\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"dockersamples/examplevotingapp_vote:before\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"vote\",\n                \"resources\": {}\n              }\n            ],\n            \"affinity\": {\n              \"nodeAffinity\": {\n                \"requiredDuringSchedulingIgnoredDuringExecution\": {\n                  \"nodeSelectorTerms\": [\n                    {\n                      \"matchExpressions\": [\n                        {\n                          \"key\": \"kubernetes.io/hostname\",\n                          \"operator\": \"In\",\n                          \"values\": [\"machine\"]\n                        }\n                      ]\n                    }\n                  ]\n                }\n              }\n            },\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-deploy-os.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"db\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"db:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"db\",\n                \"image\": \" \",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"affinity\": {\n              \"nodeAffinity\": {\n                \"requiredDuringSchedulingIgnoredDuringExecution\": {\n                  \"nodeSelectorTerms\": [\n                    {\n                      \"matchExpressions\": [\n                        {\n                          \"key\": \"kubernetes.io/hostname\",\n                          \"operator\": \"In\",\n                          \"values\": [\"machine\"]\n                        },\n                        {\n                          \"key\": \"kubernetes.io/os\",\n                          \"operator\": \"In\",\n                          \"values\": [\"ubuntu 14.04\"]\n                        },\n                        {\n                          \"key\": \"foo\",\n                          \"operator\": \"NotIn\",\n                          \"values\": [\"bar\"]\n                        }\n                      ]\n                    }\n                  ]\n                }\n              }\n            }\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"postgres\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"DaemonSet\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"com.example.description\": \"This label will appear on the web service\",\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {\n        \"currentNumberScheduled\": 0,\n        \"desiredNumberScheduled\": 0,\n        \"numberMisscheduled\": 0\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Rolling\",\n          \"rollingParams\": {\n            \"updatePeriodSeconds\": 10,\n            \"maxUnavailable\": 2,\n            \"maxSurge\": 0\n          },\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"foo\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"foo:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"foo\",\n                \"image\": \" \",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"vote\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Rolling\",\n          \"rollingParams\": {\n            \"updatePeriodSeconds\": 10,\n            \"maxUnavailable\": 2,\n            \"maxSurge\": 0\n          },\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"vote\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"vote:before\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 2,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"vote\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"vote\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"vote\",\n                \"image\": \" \",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"affinity\": {\n              \"nodeAffinity\": {\n                \"requiredDuringSchedulingIgnoredDuringExecution\": {\n                  \"nodeSelectorTerms\": [\n                    {\n                      \"matchExpressions\": [\n                        {\n                          \"key\": \"kubernetes.io/hostname\",\n                          \"operator\": \"In\",\n                          \"values\": [\"machine\"]\n                        }\n                      ]\n                    }\n                  ]\n                }\n              }\n            }\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"vote\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"vote\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"before\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"dockersamples/examplevotingapp_vote:before\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-env-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"foo\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"FOO\",\n                    \"value\": \"foo\"\n                  }\n                ],\n                \"image\": \"foo/bar:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-env-subs.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"foo\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"FOO\"\n                  }\n                ],\n                \"image\": \"foo/bar:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-k8s-3.5.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"helloworld\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"helloworld\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          },\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"helloworld\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"helloworld\"\n        },\n        \"name\": \"helloworld\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"helloworld\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.network/helloworld-network\": \"true\",\n              \"io.kompose.service\": \"helloworld\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tutum/hello-world\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"helloworld\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  },\n                  {\n                    \"containerPort\": 3000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"helloworld-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/helloworld-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/helloworld-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-k8s-full-example-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Pod\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.network/other-network\": \"true\",\n          \"io.kompose.network/other-other-network\": \"true\",\n          \"io.kompose.network/some-network\": \"true\",\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"volumes\": [\n          {\n            \"name\": \"foo-claim0\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim0\"\n            }\n          },\n          {\n            \"name\": \"foo-claim1\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim1\"\n            }\n          },\n          {\n            \"name\": \"foo-claim2\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim2\"\n            }\n          },\n          {\n            \"name\": \"foo-claim3\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim3\"\n            }\n          },\n          {\n            \"name\": \"foo-claim4\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim4\",\n              \"readOnly\": true\n            }\n          },\n          {\n            \"name\": \"datavolume\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"datavolume\"\n            }\n          },\n          {\n            \"name\": \"foo-tmpfs0\",\n            \"emptyDir\": {\n              \"medium\": \"Memory\"\n            }\n          },\n          {\n            \"name\": \"foo-tmpfs1\",\n            \"emptyDir\": {\n              \"medium\": \"Memory\"\n            }\n          }\n        ],\n        \"containers\": [\n          {\n            \"name\": \"my-web-container\",\n            \"image\": \"redis\",\n            \"command\": [\n              \"/code/entrypoint.sh\",\n              \"-p\",\n              \"3000\"\n            ],\n            \"args\": [\n              \"bundle\",\n              \"exec\",\n              \"thin\",\n              \"-p\",\n              \"3000\"\n            ],\n            \"workingDir\": \"/code\",\n            \"ports\": [\n              {\n                \"containerPort\": 3000\n              },\n              {\n                \"containerPort\": 3000\n              },\n              {\n                \"containerPort\": 3001\n              },\n              {\n                \"containerPort\": 3002\n              },\n              {\n                \"containerPort\": 3003\n              },\n              {\n                \"containerPort\": 3004\n              },\n              {\n                \"containerPort\": 3005\n              },\n              {\n                \"containerPort\": 8000\n              },\n              {\n                \"containerPort\": 8080\n              },\n              {\n                \"containerPort\": 8081\n              },\n              {\n                \"containerPort\": 22\n              },\n              {\n                \"containerPort\": 8001\n              },\n              {\n                \"containerPort\": 5000\n              },\n              {\n                \"containerPort\": 5001\n              },\n              {\n                \"containerPort\": 5002\n              },\n              {\n                \"containerPort\": 5003\n              },\n              {\n                \"containerPort\": 5004\n              },\n              {\n                \"containerPort\": 5005\n              },\n              {\n                \"containerPort\": 5006\n              },\n              {\n                \"containerPort\": 5007\n              },\n              {\n                \"containerPort\": 5008\n              },\n              {\n                \"containerPort\": 5009\n              },\n              {\n                \"containerPort\": 5010\n              }\n            ],\n            \"resources\": {\n              \"limits\": {\n                \"memory\": \"52428800\"\n              }\n            },\n            \"volumeMounts\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-claim2\",\n                \"mountPath\": \"/code\"\n              },\n              {\n                \"name\": \"foo-claim3\",\n                \"mountPath\": \"/var/www/html\"\n              },\n              {\n                \"name\": \"foo-claim4\",\n                \"readOnly\": true,\n                \"mountPath\": \"/etc/configs/\"\n              },\n              {\n                \"name\": \"datavolume\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-tmpfs0\",\n                \"mountPath\": \"/run\"\n              },\n              {\n                \"name\": \"foo-tmpfs1\",\n                \"mountPath\": \"/tmp\"\n              }\n            ],\n            \"securityContext\": {\n              \"capabilities\": {\n                \"add\": [\n                  \"ALL\"\n                ],\n                \"drop\": [\n                  \"NET_ADMIN\",\n                  \"SYS_ADMIN\"\n                ]\n              },\n              \"privileged\": true\n            },\n            \"stdin\": true,\n            \"tty\": true\n          }\n        ],\n        \"restartPolicy\": \"OnFailure\"\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim2\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim3\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim4\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim4\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadOnlyMany\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"datavolume\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"datavolume\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"other-other-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/other-other-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/other-other-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"some-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/some-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/some-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"other-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/other-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/other-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-k8s-full-example.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Accounting webapp\",\n          \"com.example.empty-label\": \"\",\n          \"com.example.number\": \"42\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"3000-tcp\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"3001\",\n            \"port\": 3001,\n            \"targetPort\": 3001\n          },\n          {\n            \"name\": \"3002\",\n            \"port\": 3002,\n            \"targetPort\": 3002\n          },\n          {\n            \"name\": \"3003\",\n            \"port\": 3003,\n            \"targetPort\": 3003\n          },\n          {\n            \"name\": \"3004\",\n            \"port\": 3004,\n            \"targetPort\": 3004\n          },\n          {\n            \"name\": \"3005\",\n            \"port\": 3005,\n            \"targetPort\": 3005\n          },\n          {\n            \"name\": \"8000\",\n            \"port\": 8000,\n            \"targetPort\": 8000\n          },\n          {\n            \"name\": \"9090\",\n            \"port\": 9090,\n            \"targetPort\": 8080\n          },\n          {\n            \"name\": \"9091\",\n            \"port\": 9091,\n            \"targetPort\": 8081\n          },\n          {\n            \"name\": \"49100\",\n            \"port\": 49100,\n            \"targetPort\": 22\n          },\n          {\n            \"name\": \"8001\",\n            \"port\": 8001,\n            \"targetPort\": 8001\n          },\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          },\n          {\n            \"name\": \"5001\",\n            \"port\": 5001,\n            \"targetPort\": 5001\n          },\n          {\n            \"name\": \"5002\",\n            \"port\": 5002,\n            \"targetPort\": 5002\n          },\n          {\n            \"name\": \"5003\",\n            \"port\": 5003,\n            \"targetPort\": 5003\n          },\n          {\n            \"name\": \"5004\",\n            \"port\": 5004,\n            \"targetPort\": 5004\n          },\n          {\n            \"name\": \"5005\",\n            \"port\": 5005,\n            \"targetPort\": 5005\n          },\n          {\n            \"name\": \"5006\",\n            \"port\": 5006,\n            \"targetPort\": 5006\n          },\n          {\n            \"name\": \"5007\",\n            \"port\": 5007,\n            \"targetPort\": 5007\n          },\n          {\n            \"name\": \"5008\",\n            \"port\": 5008,\n            \"targetPort\": 5008\n          },\n          {\n            \"name\": \"5009\",\n            \"port\": 5009,\n            \"targetPort\": 5009\n          },\n          {\n            \"name\": \"5010\",\n            \"port\": 5010,\n            \"targetPort\": 5010\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Pod\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.network/other-network\": \"true\",\n          \"io.kompose.network/other-other-network\": \"true\",\n          \"io.kompose.network/some-network\": \"true\",\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Accounting webapp\",\n          \"com.example.empty-label\": \"\",\n          \"com.example.number\": \"42\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"volumes\": [\n          {\n            \"name\": \"foo-claim0\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim0\"\n            }\n          },\n          {\n            \"name\": \"foo-claim1\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim1\"\n            }\n          },\n          {\n            \"name\": \"foo-claim2\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim2\"\n            }\n          },\n          {\n            \"name\": \"foo-claim3\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim3\"\n            }\n          },\n          {\n            \"name\": \"foo-claim4\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim4\",\n              \"readOnly\": true\n            }\n          },\n          {\n            \"name\": \"datavolume\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"datavolume\"\n            }\n          },\n          {\n            \"name\": \"foo-tmpfs0\",\n            \"emptyDir\": {\n              \"medium\": \"Memory\"\n            }\n          },\n          {\n            \"name\": \"foo-tmpfs1\",\n            \"emptyDir\": {\n              \"medium\": \"Memory\"\n            }\n          }\n        ],\n        \"containers\": [\n          {\n            \"name\": \"my-web-container\",\n            \"image\": \"redis\",\n            \"command\": [\n              \"/code/entrypoint.sh\",\n              \"-p\",\n              \"3000\"\n            ],\n            \"args\": [\n              \"bundle\",\n              \"exec\",\n              \"thin\",\n              \"-p\",\n              \"3000\"\n            ],\n            \"workingDir\": \"/code\",\n            \"ports\": [\n              {\n                \"containerPort\": 3000\n              },\n              {\n                \"containerPort\": 3001\n              },\n              {\n                \"containerPort\": 3002\n              },\n              {\n                \"containerPort\": 3003\n              },\n              {\n                \"containerPort\": 3004\n              },\n              {\n                \"containerPort\": 3005\n              },\n              {\n                \"containerPort\": 8000\n              },\n              {\n                \"containerPort\": 8080\n              },\n              {\n                \"containerPort\": 8081\n              },\n              {\n                \"containerPort\": 22\n              },\n              {\n                \"containerPort\": 8001\n              },\n              {\n                \"containerPort\": 5000\n              },\n              {\n                \"containerPort\": 5001\n              },\n              {\n                \"containerPort\": 5002\n              },\n              {\n                \"containerPort\": 5003\n              },\n              {\n                \"containerPort\": 5004\n              },\n              {\n                \"containerPort\": 5005\n              },\n              {\n                \"containerPort\": 5006\n              },\n              {\n                \"containerPort\": 5007\n              },\n              {\n                \"containerPort\": 5008\n              },\n              {\n                \"containerPort\": 5009\n              },\n              {\n                \"containerPort\": 5010\n              }\n            ],\n            \"resources\": {\n              \"limits\": {\n                \"cpu\": \"1m\",\n                \"memory\": \"52428800\"\n              },\n              \"requests\": {\n                \"memory\": \"20971520\"\n              }\n            },\n            \"volumeMounts\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-claim2\",\n                \"mountPath\": \"/code\"\n              },\n              {\n                \"name\": \"foo-claim3\",\n                \"mountPath\": \"/var/www/html\"\n              },\n              {\n                \"name\": \"foo-claim4\",\n                \"readOnly\": true,\n                \"mountPath\": \"/etc/configs/\"\n              },\n              {\n                \"name\": \"datavolume\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-tmpfs0\",\n                \"mountPath\": \"/run\"\n              },\n              {\n                \"name\": \"foo-tmpfs1\",\n                \"mountPath\": \"/tmp\"\n              }\n            ],\n            \"livenessProbe\": {\n              \"exec\": {\n                \"command\": [\n                  \"echo \\\"hello world\\\"\"\n                ]\n              },\n              \"timeoutSeconds\": 1,\n              \"periodSeconds\": 10,\n              \"failureThreshold\": 5\n            },\n            \"securityContext\": {\n              \"capabilities\": {\n                \"add\": [\n                  \"ALL\"\n                ],\n                \"drop\": [\n                  \"NET_ADMIN\",\n                  \"SYS_ADMIN\"\n                ]\n              },\n              \"privileged\": true\n            },\n            \"stdin\": true,\n            \"tty\": true\n          }\n        ],\n        \"restartPolicy\": \"OnFailure\",\n        \"terminationGracePeriodSeconds\": 20,\n        \"hostname\": \"foo\",\n        \"subdomain\": \"foo.com\"\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim2\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim3\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim4\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim4\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadOnlyMany\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"datavolume\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"datavolume\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"some-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/some-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/some-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"other-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/other-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/other-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"kind\": \"NetworkPolicy\",\n      \"apiVersion\": \"extensions/v1beta1\",\n      \"metadata\": {\n        \"name\": \"other-other-network\",\n        \"creationTimestamp\": null\n      },\n      \"spec\": {\n        \"podSelector\": {\n          \"matchLabels\": {\n            \"io.kompose.network/other-other-network\": \"true\"\n          }\n        },\n        \"ingress\": [\n          {\n            \"from\": [\n              {\n                \"podSelector\": {\n                  \"matchLabels\": {\n                    \"io.kompose.network/other-other-network\": \"true\"\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"name\": \"frontend\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"frontend\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"LoadBalancer\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"gcr.io/google-samples/gb-frontend:v4\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"frontend\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"name\": \"redis-master\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-master\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-master\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"name\": \"redis-replica\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-replica\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"image\": \"registry.k8s.io/redis-slave:v2\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-replica\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-memcpu-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"foo\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {\n                  \"limits\": {\n                    \"cpu\": \"10m\",\n                    \"memory\": \"52428800\"\n                  },\n                  \"requests\": {\n                    \"cpu\": \"1m\",\n                    \"memory\": \"20971520\"\n                  }\n                }\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-memcpu-partial-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"foo\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {\n                  \"limits\": {\n                    \"memory\": \"52428800\"\n                  },\n                  \"requests\": {\n                    \"cpu\": \"1m\"\n                  }\n                }\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-os-full-example.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Accounting webapp\",\n          \"com.example.empty-label\": \"\",\n          \"com.example.number\": \"42\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3000\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"3000-tcp\",\n            \"port\": 3000,\n            \"targetPort\": 3000\n          },\n          {\n            \"name\": \"3001\",\n            \"port\": 3001,\n            \"targetPort\": 3001\n          },\n          {\n            \"name\": \"3002\",\n            \"port\": 3002,\n            \"targetPort\": 3002\n          },\n          {\n            \"name\": \"3003\",\n            \"port\": 3003,\n            \"targetPort\": 3003\n          },\n          {\n            \"name\": \"3004\",\n            \"port\": 3004,\n            \"targetPort\": 3004\n          },\n          {\n            \"name\": \"3005\",\n            \"port\": 3005,\n            \"targetPort\": 3005\n          },\n          {\n            \"name\": \"8000\",\n            \"port\": 8000,\n            \"targetPort\": 8000\n          },\n          {\n            \"name\": \"9090\",\n            \"port\": 9090,\n            \"targetPort\": 8080\n          },\n          {\n            \"name\": \"9091\",\n            \"port\": 9091,\n            \"targetPort\": 8081\n          },\n          {\n            \"name\": \"49100\",\n            \"port\": 49100,\n            \"targetPort\": 22\n          },\n          {\n            \"name\": \"8001\",\n            \"port\": 8001,\n            \"targetPort\": 8001\n          },\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          },\n          {\n            \"name\": \"5001\",\n            \"port\": 5001,\n            \"targetPort\": 5001\n          },\n          {\n            \"name\": \"5002\",\n            \"port\": 5002,\n            \"targetPort\": 5002\n          },\n          {\n            \"name\": \"5003\",\n            \"port\": 5003,\n            \"targetPort\": 5003\n          },\n          {\n            \"name\": \"5004\",\n            \"port\": 5004,\n            \"targetPort\": 5004\n          },\n          {\n            \"name\": \"5005\",\n            \"port\": 5005,\n            \"targetPort\": 5005\n          },\n          {\n            \"name\": \"5006\",\n            \"port\": 5006,\n            \"targetPort\": 5006\n          },\n          {\n            \"name\": \"5007\",\n            \"port\": 5007,\n            \"targetPort\": 5007\n          },\n          {\n            \"name\": \"5008\",\n            \"port\": 5008,\n            \"targetPort\": 5008\n          },\n          {\n            \"name\": \"5009\",\n            \"port\": 5009,\n            \"targetPort\": 5009\n          },\n          {\n            \"name\": \"5010\",\n            \"port\": 5010,\n            \"targetPort\": 5010\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Pod\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.network/other-network\": \"true\",\n          \"io.kompose.network/other-other-network\": \"true\",\n          \"io.kompose.network/some-network\": \"true\",\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"com.example.description\": \"Accounting webapp\",\n          \"com.example.empty-label\": \"\",\n          \"com.example.number\": \"42\",\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"volumes\": [\n          {\n            \"name\": \"foo-claim0\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim0\"\n            }\n          },\n          {\n            \"name\": \"foo-claim1\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim1\"\n            }\n          },\n          {\n            \"name\": \"foo-claim2\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim2\"\n            }\n          },\n          {\n            \"name\": \"foo-claim3\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim3\"\n            }\n          },\n          {\n            \"name\": \"foo-claim4\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"foo-claim4\",\n              \"readOnly\": true\n            }\n          },\n          {\n            \"name\": \"datavolume\",\n            \"persistentVolumeClaim\": {\n              \"claimName\": \"datavolume\"\n            }\n          },\n          {\n            \"name\": \"foo-tmpfs0\",\n            \"emptyDir\": {\n              \"medium\": \"Memory\"\n            }\n          },\n          {\n            \"name\": \"foo-tmpfs1\",\n            \"emptyDir\": {\n              \"medium\": \"Memory\"\n            }\n          }\n        ],\n        \"containers\": [\n          {\n            \"name\": \"my-web-container\",\n            \"image\": \"redis\",\n            \"command\": [\n              \"/code/entrypoint.sh\",\n              \"-p\",\n              \"3000\"\n            ],\n            \"args\": [\n              \"bundle\",\n              \"exec\",\n              \"thin\",\n              \"-p\",\n              \"3000\"\n            ],\n            \"workingDir\": \"/code\",\n            \"ports\": [\n              {\n                \"containerPort\": 3000\n              },\n              {\n                \"containerPort\": 3001\n              },\n              {\n                \"containerPort\": 3002\n              },\n              {\n                \"containerPort\": 3003\n              },\n              {\n                \"containerPort\": 3004\n              },\n              {\n                \"containerPort\": 3005\n              },\n              {\n                \"containerPort\": 8000\n              },\n              {\n                \"containerPort\": 8080\n              },\n              {\n                \"containerPort\": 8081\n              },\n              {\n                \"containerPort\": 22\n              },\n              {\n                \"containerPort\": 8001\n              },\n              {\n                \"containerPort\": 5000\n              },\n              {\n                \"containerPort\": 5001\n              },\n              {\n                \"containerPort\": 5002\n              },\n              {\n                \"containerPort\": 5003\n              },\n              {\n                \"containerPort\": 5004\n              },\n              {\n                \"containerPort\": 5005\n              },\n              {\n                \"containerPort\": 5006\n              },\n              {\n                \"containerPort\": 5007\n              },\n              {\n                \"containerPort\": 5008\n              },\n              {\n                \"containerPort\": 5009\n              },\n              {\n                \"containerPort\": 5010\n              }\n            ],\n            \"resources\": {\n              \"limits\": {\n                \"cpu\": \"1m\",\n                \"memory\": \"52428800\"\n              },\n              \"requests\": {\n                \"memory\": \"20971520\"\n              }\n            },\n            \"volumeMounts\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-claim2\",\n                \"mountPath\": \"/code\"\n              },\n              {\n                \"name\": \"foo-claim3\",\n                \"mountPath\": \"/var/www/html\"\n              },\n              {\n                \"name\": \"foo-claim4\",\n                \"readOnly\": true,\n                \"mountPath\": \"/etc/configs/\"\n              },\n              {\n                \"name\": \"datavolume\",\n                \"mountPath\": \"/var/lib/mysql\"\n              },\n              {\n                \"name\": \"foo-tmpfs0\",\n                \"mountPath\": \"/run\"\n              },\n              {\n                \"name\": \"foo-tmpfs1\",\n                \"mountPath\": \"/tmp\"\n              }\n            ],\n            \"livenessProbe\": {\n              \"exec\": {\n                \"command\": [\n                  \"echo \\\"hello world\\\"\"\n                ]\n              },\n              \"timeoutSeconds\": 1,\n              \"periodSeconds\": 10,\n              \"failureThreshold\": 5\n            },\n            \"securityContext\": {\n              \"capabilities\": {\n                \"add\": [\n                  \"ALL\"\n                ],\n                \"drop\": [\n                  \"NET_ADMIN\",\n                  \"SYS_ADMIN\"\n                ]\n              },\n              \"privileged\": true\n            },\n            \"stdin\": true,\n            \"tty\": true\n          }\n        ],\n        \"restartPolicy\": \"OnFailure\",\n\t\"terminationGracePeriodSeconds\": 20,\n        \"hostname\": \"foo\",\n        \"subdomain\": \"foo.com\"\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim2\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim2\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim3\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim3\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim4\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim4\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadOnlyMany\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"datavolume\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"datavolume\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"type\": \"LoadBalancer\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"LoadBalancer\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"frontend\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"frontend:v4\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"frontend\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"frontend\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"frontend\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"frontend\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"frontend\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"v4\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"gcr.io/google-samples/gb-frontend:v4\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-master\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-master:e2e\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-master\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"e2e\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis:e2e\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-replica\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-replica:v1\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-replica\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-replica\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis-replica\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"env\": [\n                  {\n                    \"name\": \"GET_HOSTS_FROM\",\n                    \"value\": \"dns\"\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-replica\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-replica\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"v1\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis-slave:v2\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-unset-env-k8s.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"name\": \"foo\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"foo\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"env\": [\n                  {\n                    \"name\": \"FOO\",\n                    \"value\": \"foo\"\n                  },\n                  {\n                    \"name\": \"V3_HOST_ENV_TEST_SET_TO_BAR\",\n                    \"value\": \"BAR\"\n                  }\n                ],\n                \"image\": \"foo/bar:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foo\",\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/unused/v3/output-volumes-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foobar\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foobar\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foobar\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.service.type\": \"headless\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foobar\"\n        },\n        \"name\": \"foobar\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"foobar\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.service.type\": \"headless\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foobar\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"foo/bar:latest\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"foobar\",\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/tmp/foo/bar\",\n                    \"name\": \"foobar-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"foobar-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foobar-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foobar-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foobar-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/v2/compose.yaml",
    "content": "\nservices:\n  foo:\n    # create a pod\n    image: \"foobar\"\n    restart: \"no\"\n    environment:\n      GITHUB: surajssd\n    ports:\n      - \"6379/tcp\"\n      - \"6379/udp\"\n      - \"3000\"\n      - \"3000-3005\"\n      - \"8000:8000\"\n      - \"9090-9091:8080-8081\"\n      - \"49100:22\"\n      - \"127.0.0.1:8001:8001\"\n      - \"127.0.0.1:5000-5010:5000-5010\"\n    mem_limit: 10000\n\n    group_add:\n      - \"1234\"\n\n  redis:\n    image: redis:3.0\n    labels:\n      kompose.service.type: loadbalancer\n    ports:\n      - \"6379/tcp\"\n      - \"1234:1235/udp\"\n\n    mem_limit: 10000Mb\n\n\n"
  },
  {
    "path": "script/test/fixtures/v2/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n    - name: 6379-udp\n      port: 6379\n      protocol: UDP\n      targetPort: 6379\n    - name: \"3000\"\n      port: 3000\n      targetPort: 3000\n    - name: \"3001\"\n      port: 3001\n      targetPort: 3001\n    - name: \"3002\"\n      port: 3002\n      targetPort: 3002\n    - name: \"3003\"\n      port: 3003\n      targetPort: 3003\n    - name: \"3004\"\n      port: 3004\n      targetPort: 3004\n    - name: \"3005\"\n      port: 3005\n      targetPort: 3005\n    - name: \"8000\"\n      port: 8000\n      targetPort: 8000\n    - name: \"9090\"\n      port: 9090\n      targetPort: 8080\n    - name: \"9091\"\n      port: 9091\n      targetPort: 8081\n    - name: \"49100\"\n      port: 49100\n      targetPort: 22\n    - name: \"8001\"\n      port: 8001\n      targetPort: 8001\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n    - name: \"5001\"\n      port: 5001\n      targetPort: 5001\n    - name: \"5002\"\n      port: 5002\n      targetPort: 5002\n    - name: \"5003\"\n      port: 5003\n      targetPort: 5003\n    - name: \"5004\"\n      port: 5004\n      targetPort: 5004\n    - name: \"5005\"\n      port: 5005\n      targetPort: 5005\n    - name: \"5006\"\n      port: 5006\n      targetPort: 5006\n    - name: \"5007\"\n      port: 5007\n      targetPort: 5007\n    - name: \"5008\"\n      port: 5008\n      targetPort: 5008\n    - name: \"5009\"\n      port: 5009\n      targetPort: 5009\n    - name: \"5010\"\n      port: 5010\n      targetPort: 5010\n  selector:\n    io.kompose.service: foo\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis-tcp\n  name: redis-tcp\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n  type: LoadBalancer\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis-udp\n  name: redis-udp\nspec:\n  ports:\n    - name: \"1234\"\n      port: 1234\n      protocol: UDP\n      targetPort: 1235\n  selector:\n    io.kompose.service: redis\n  type: LoadBalancer\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  containers:\n    - env:\n        - name: GITHUB\n          value: surajssd\n      image: foobar\n      name: foo\n      ports:\n        - containerPort: 6379\n          protocol: TCP\n        - containerPort: 6379\n          protocol: UDP\n        - containerPort: 3000\n          protocol: TCP\n        - containerPort: 3001\n          protocol: TCP\n        - containerPort: 3002\n          protocol: TCP\n        - containerPort: 3003\n          protocol: TCP\n        - containerPort: 3004\n          protocol: TCP\n        - containerPort: 3005\n          protocol: TCP\n        - containerPort: 8000\n          protocol: TCP\n        - containerPort: 8080\n          protocol: TCP\n        - containerPort: 8081\n          protocol: TCP\n        - containerPort: 22\n          protocol: TCP\n        - containerPort: 8001\n          protocol: TCP\n        - containerPort: 5000\n          protocol: TCP\n        - containerPort: 5001\n          protocol: TCP\n        - containerPort: 5002\n          protocol: TCP\n        - containerPort: 5003\n          protocol: TCP\n        - containerPort: 5004\n          protocol: TCP\n        - containerPort: 5005\n          protocol: TCP\n        - containerPort: 5006\n          protocol: TCP\n        - containerPort: 5007\n          protocol: TCP\n        - containerPort: 5008\n          protocol: TCP\n        - containerPort: 5009\n          protocol: TCP\n        - containerPort: 5010\n          protocol: TCP\n      resources:\n        limits:\n          memory: \"10e3\"\n  restartPolicy: Never\n  securityContext:\n    supplementalGroups:\n      - 1234\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: redis:3.0\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n            - containerPort: 1235\n              protocol: UDP\n          resources:\n            limits:\n              memory: \"10485760e3\"\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/v2/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n    - name: 6379-udp\n      port: 6379\n      protocol: UDP\n      targetPort: 6379\n    - name: \"3000\"\n      port: 3000\n      targetPort: 3000\n    - name: \"3001\"\n      port: 3001\n      targetPort: 3001\n    - name: \"3002\"\n      port: 3002\n      targetPort: 3002\n    - name: \"3003\"\n      port: 3003\n      targetPort: 3003\n    - name: \"3004\"\n      port: 3004\n      targetPort: 3004\n    - name: \"3005\"\n      port: 3005\n      targetPort: 3005\n    - name: \"8000\"\n      port: 8000\n      targetPort: 8000\n    - name: \"9090\"\n      port: 9090\n      targetPort: 8080\n    - name: \"9091\"\n      port: 9091\n      targetPort: 8081\n    - name: \"49100\"\n      port: 49100\n      targetPort: 22\n    - name: \"8001\"\n      port: 8001\n      targetPort: 8001\n    - name: \"5000\"\n      port: 5000\n      targetPort: 5000\n    - name: \"5001\"\n      port: 5001\n      targetPort: 5001\n    - name: \"5002\"\n      port: 5002\n      targetPort: 5002\n    - name: \"5003\"\n      port: 5003\n      targetPort: 5003\n    - name: \"5004\"\n      port: 5004\n      targetPort: 5004\n    - name: \"5005\"\n      port: 5005\n      targetPort: 5005\n    - name: \"5006\"\n      port: 5006\n      targetPort: 5006\n    - name: \"5007\"\n      port: 5007\n      targetPort: 5007\n    - name: \"5008\"\n      port: 5008\n      targetPort: 5008\n    - name: \"5009\"\n      port: 5009\n      targetPort: 5009\n    - name: \"5010\"\n      port: 5010\n      targetPort: 5010\n  selector:\n    io.kompose.service: foo\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis-tcp\n  name: redis-tcp\nspec:\n  ports:\n    - name: \"6379\"\n      port: 6379\n      targetPort: 6379\n  selector:\n    io.kompose.service: redis\n  type: LoadBalancer\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis-udp\n  name: redis-udp\nspec:\n  ports:\n    - name: \"1234\"\n      port: 1234\n      protocol: UDP\n      targetPort: 1235\n  selector:\n    io.kompose.service: redis\n  type: LoadBalancer\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  containers:\n    - env:\n        - name: GITHUB\n          value: surajssd\n      image: foobar\n      name: foo\n      ports:\n        - containerPort: 6379\n          protocol: TCP\n        - containerPort: 6379\n          protocol: UDP\n        - containerPort: 3000\n          protocol: TCP\n        - containerPort: 3001\n          protocol: TCP\n        - containerPort: 3002\n          protocol: TCP\n        - containerPort: 3003\n          protocol: TCP\n        - containerPort: 3004\n          protocol: TCP\n        - containerPort: 3005\n          protocol: TCP\n        - containerPort: 8000\n          protocol: TCP\n        - containerPort: 8080\n          protocol: TCP\n        - containerPort: 8081\n          protocol: TCP\n        - containerPort: 22\n          protocol: TCP\n        - containerPort: 8001\n          protocol: TCP\n        - containerPort: 5000\n          protocol: TCP\n        - containerPort: 5001\n          protocol: TCP\n        - containerPort: 5002\n          protocol: TCP\n        - containerPort: 5003\n          protocol: TCP\n        - containerPort: 5004\n          protocol: TCP\n        - containerPort: 5005\n          protocol: TCP\n        - containerPort: 5006\n          protocol: TCP\n        - containerPort: 5007\n          protocol: TCP\n        - containerPort: 5008\n          protocol: TCP\n        - containerPort: 5009\n          protocol: TCP\n        - containerPort: 5010\n          protocol: TCP\n      resources:\n        limits:\n          memory: \"10e3\"\n  restartPolicy: Never\n  securityContext:\n    supplementalGroups:\n      - 1234\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: ' '\n          name: redis\n          ports:\n            - containerPort: 6379\n              protocol: TCP\n            - containerPort: 1235\n              protocol: UDP\n          resources:\n            limits:\n              memory: \"10485760e3\"\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:3.0\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis:3.0\n      name: \"3.0\"\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/v3.0/compose.yaml",
    "content": "\nservices:\n  redis:\n    image: redis\n    labels:\n      kompose.service.type: headless\n    healthcheck:\n      test: echo \"hello world\"\n      interval: 10s\n      timeout: 1s\n      retries: 5\n    restart: \"unless-stopped\"\n  foo:\n    image: foo:latest\n    command: sh -c \"echo Hello Foo\"\n    networks:\n      app: {}\n      web: {}\n      normalized_network: {}\nnetworks:\n  normalized_network:\n  app:\n    external:\n      name: app-network\n  web:\n    external:\n      name: web-network\n"
  },
  {
    "path": "script/test/fixtures/v3.0/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  clusterIP: None\n  ports:\n    - name: headless\n      port: 55555\n      targetPort: 0\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: foo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: foo\n    spec:\n      containers:\n        - args:\n            - sh\n            - -c\n            - echo Hello Foo\n          image: foo:latest\n          name: foo\n      restartPolicy: Always\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: redis\n          livenessProbe:\n            exec:\n              command:\n                - echo \"hello world\"\n            failureThreshold: 5\n            periodSeconds: 10\n            timeoutSeconds: 1\n          name: redis\n      restartPolicy: Always\n\n"
  },
  {
    "path": "script/test/fixtures/v3.0/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  clusterIP: None\n  ports:\n    - name: headless\n      port: 55555\n      targetPort: 0\n  selector:\n    io.kompose.service: redis\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: foo\n  template:\n    metadata:\n      labels:\n        io.kompose.service: foo\n    spec:\n      containers:\n        - args:\n            - sh\n            - -c\n            - echo Hello Foo\n          image: ' '\n          name: foo\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - foo\n        from:\n          kind: ImageStreamTag\n          name: foo:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: foo\n  name: foo\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: foo:latest\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: redis\n  template:\n    metadata:\n      labels:\n        io.kompose.service: redis\n    spec:\n      containers:\n        - image: ' '\n          livenessProbe:\n            exec:\n              command:\n                - echo \"hello world\"\n            failureThreshold: 5\n            periodSeconds: 10\n            timeoutSeconds: 1\n          name: redis\n      restartPolicy: Always\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - redis\n        from:\n          kind: ImageStreamTag\n          name: redis:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: redis\n  name: redis\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: redis\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n"
  },
  {
    "path": "script/test/fixtures/vols-subpath/compose.yaml",
    "content": "volumes:\n  postgres-data:\n\nservices:\n  postgres:\n    labels:\n      kompose.volume.subpath: test\n    image: postgres\n    environment:\n      POSTGRES_USER: dumb_postgres_user\n      POSTGRES_PASSWORD: postgres_password\n      POSTGRES_DB: dumb_db\n    volumes:\n      - postgres-data:/var/lib/postgresql/data\n"
  },
  {
    "path": "script/test/fixtures/vols-subpath/output-k8s.yaml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: postgres\n  name: postgres\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: postgres\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: postgres\n    spec:\n      containers:\n        - env:\n            - name: POSTGRES_DB\n              value: dumb_db\n            - name: POSTGRES_PASSWORD\n              value: postgres_password\n            - name: POSTGRES_USER\n              value: dumb_postgres_user\n          image: postgres\n          name: postgres\n          volumeMounts:\n            - mountPath: /var/lib/postgresql/data\n              name: postgres-data\n              subPath: test\n      restartPolicy: Always\n      volumes:\n        - name: postgres-data\n          persistentVolumeClaim:\n            claimName: postgres-data\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: postgres-data\n  name: postgres-data\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n"
  },
  {
    "path": "script/test/fixtures/vols-subpath/output-os.yaml",
    "content": "---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: postgres\n  name: postgres\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: postgres\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: postgres\n    spec:\n      containers:\n        - env:\n            - name: POSTGRES_DB\n              value: dumb_db\n            - name: POSTGRES_PASSWORD\n              value: postgres_password\n            - name: POSTGRES_USER\n              value: dumb_postgres_user\n          image: ' '\n          name: postgres\n          volumeMounts:\n            - mountPath: /var/lib/postgresql/data\n              name: postgres-data\n              subPath: test\n      restartPolicy: Always\n      volumes:\n        - name: postgres-data\n          persistentVolumeClaim:\n            claimName: postgres-data\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - postgres\n        from:\n          kind: ImageStreamTag\n          name: postgres:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: postgres\n  name: postgres\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: postgres\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: postgres-data\n  name: postgres-data\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/hostpath/docker-compose-v3.yml",
    "content": "services:\n  db:\n    image: postgres:10.1\n    ports:\n      - \"5432\"\n    volumes:\n      - ./data_sux:/var/lib/postgresql/data_sux"
  },
  {
    "path": "script/test/fixtures/volume-mounts/hostpath/docker-compose.yml",
    "content": "services:\n  db:\n    image: postgres:10.1\n    ports:\n      - \"5432\"\n    volumes:\n      - ./data_sux:/var/lib/postgresql/data_sux"
  },
  {
    "path": "script/test/fixtures/volume-mounts/hostpath/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"name\": \"db\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"db\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"postgres:10.1\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"db\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/lib/postgresql/data_sux\",\n                    \"name\": \"db-hostpath0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"hostPath\": {\n                  \"path\": \"%HOSTPATH%\"\n                },\n                \"name\": \"db-hostpath0\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/hostpath/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"db\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"db:10.1\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"db-hostpath0\",\n                \"hostPath\": {\n                  \"path\": \"%HOSTPATH%\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"db\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"db-hostpath0\",\n                    \"mountPath\": \"/var/lib/postgresql/data_sux\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"10.1\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"postgres:10.1\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/named-volume/docker-compose-v3.yml",
    "content": "services:\n  db:\n    image: postgres:10.1\n    ports:\n      - \"5432\"\n    labels:\n      kompose.volume.size: 200Mi\n    volumes:\n      - db-data:/var/lib/postgresql/data\n      - db-config:/var/lib/postgresql/config\nvolumes:\n  db-data:\n    labels:\n      kompose.volume.selector: db-data-dev\n      kompose.volume.size: 500Mi"
  },
  {
    "path": "script/test/fixtures/volume-mounts/named-volume/docker-compose.yml",
    "content": "services:\n  db:\n    image: postgres:10.1\n    ports:\n      - \"5432\"\n    labels:\n      kompose.volume.size: 1Gi\n    volumes:\n      - db-data:/var/lib/postgresql/data"
  },
  {
    "path": "script/test/fixtures/volume-mounts/named-volume/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"1Gi\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"1Gi\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"name\": \"db\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"db\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\",\n              \"kompose.volume.size\": \"1Gi\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"postgres:10.1\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"db\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/lib/postgresql/data\",\n                    \"name\": \"db-data\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"db-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"db-data\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"1Gi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/named-volume/output-k8s-v3.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"200Mi\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"200Mi\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"name\": \"db\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"db\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\",\n              \"kompose.volume.size\": \"200Mi\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"postgres:10.1\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"db\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/lib/postgresql/data\",\n                    \"name\": \"db-data\"\n                  },\n                  {\n                    \"mountPath\": \"/var/lib/postgresql/config\",\n                    \"name\": \"db-config\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"db-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"db-data\"\n                }\n              },\n              {\n                \"name\": \"db-config\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"db-config\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"db-data-dev\"\n          }\n        },\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"500Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db-config\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db-config\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"200Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/named-volume/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"1Gi\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5432\",\n            \"port\": 5432,\n            \"targetPort\": 5432\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\",\n          \"kompose.volume.size\": \"1Gi\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"db\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"db:10.1\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"db\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"db\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"db-data\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"db-data\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"db\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5432\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"db-data\",\n                    \"mountPath\": \"/var/lib/postgresql/data\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"10.1\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"postgres:10.1\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"db-data\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"db-data\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"1Gi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/simple-vol-mounts/docker-compose.yml",
    "content": "\nservices:\n  httpd:\n    image: docker.io/fedora/apache\n    ports:\n      - \"80\"\n    volumes:\n      - /var/www/html\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/simple-vol-mounts/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"httpd\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"httpd\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd\"\n        },\n        \"name\": \"httpd\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"httpd\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"httpd\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"docker.io/fedora/apache\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"httpd\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/var/www/html\",\n                    \"name\": \"httpd-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"httpd-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"httpd-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"httpd-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/simple-vol-mounts/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"httpd\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"httpd\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"httpd\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"httpd\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"httpd:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"httpd\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"httpd\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"httpd-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"httpd-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"httpd\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"httpd-claim0\",\n                    \"mountPath\": \"/var/www/html\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"httpd\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"docker.io/fedora/apache\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"httpd-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"httpd-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/tmpfs/docker-compose.yml",
    "content": "\nservices:\n\n  redis-master:\n    image: registry.k8s.io/redis:e2e \n    ports:\n      - \"6379\"\n    tmpfs:\n      - /tmp:rw,noexec,nosuid\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/tmpfs/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"name\": \"redis-master\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis-master\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"registry.k8s.io/redis:e2e\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis-master\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/tmp\",\n                    \"name\": \"redis-master-tmpfs0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"emptyDir\": {\n                  \"medium\": \"Memory\"\n                },\n                \"name\": \"redis-master-tmpfs0\"\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/tmpfs/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis-master\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis-master:e2e\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis-master\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis-master\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"redis-master-tmpfs0\",\n                \"emptyDir\": {\n                  \"medium\": \"Memory\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"redis-master\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"redis-master-tmpfs0\",\n                    \"mountPath\": \"/tmp\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis-master\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis-master\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"e2e\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"registry.k8s.io/redis:e2e\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/volumes-from/docker-compose-case.yml",
    "content": "\nservices:\n\n  foo:\n    image: busybox\n    command: sleep 3600\n    volumes:\n       - /foo1\n       - /foo2\n    volumes_from:\n       - cat\n\n\n  bar:\n    image: busybox\n    command: sleep 3600\n    volumes:\n       - /foo1\n       - /bar\n    volumes_from:\n       - foo\n\n  cat:\n    image: busybox\n    command: sleep 3600\n    volumes:\n      - /cat\n\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/volumes-from/docker-compose.yml",
    "content": "\nservices:\n  web:\n    image: centos/httpd\n    volumes:\n      - \"./app:/src/app\"\n    ports:\n      - \"3030:3000\"\n    command: nodemon -L app/bin/www\n\n  nginx:\n    restart: always\n    image: nginx\n    ports:\n      - \"80:80\"\n    volumes:\n      - /www/public\n    volumes_from:\n      - web\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/volumes-from/output-k8s-case.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"bar\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"cat\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"cat\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"bar\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"bar\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim0\"\n                }\n              },\n              {\n                \"name\": \"bar-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"bar-claim1\"\n                }\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim1\"\n                }\n              },\n              {\n                \"name\": \"cat-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"cat-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"bar\",\n                \"image\": \"busybox\",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"foo-claim0\",\n                    \"mountPath\": \"/foo1\"\n                  },\n                  {\n                    \"name\": \"bar-claim1\",\n                    \"mountPath\": \"/bar\"\n                  },\n                  {\n                    \"name\": \"foo-claim1\",\n                    \"mountPath\": \"/foo2\"\n                  },\n                  {\n                    \"name\": \"cat-claim0\",\n                    \"mountPath\": \"/cat\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"cat\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"cat\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"cat-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"cat-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"cat\",\n                \"image\": \"busybox\",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"cat-claim0\",\n                    \"mountPath\": \"/cat\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"cat-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"Deployment\",\n      \"apiVersion\": \"apps/v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim0\"\n                }\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim1\"\n                }\n              },\n              {\n                \"name\": \"cat-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"cat-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"foo\",\n                \"image\": \"busybox\",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"foo-claim0\",\n                    \"mountPath\": \"/foo1\"\n                  },\n                  {\n                    \"name\": \"foo-claim1\",\n                    \"mountPath\": \"/foo2\"\n                  },\n                  {\n                    \"name\": \"cat-claim0\",\n                    \"mountPath\": \"/cat\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/volumes-from/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3030\",\n            \"port\": 3030,\n            \"targetPort\": 3000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"name\": \"nginx\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"nginx\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"nginx\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"nginx\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/www/public\",\n                    \"name\": \"nginx-claim0\"\n                  },\n                  {\n                    \"mountPath\": \"/src/app\",\n                    \"name\": \"web-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"nginx-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"nginx-claim0\"\n                }\n              },\n              {\n                \"name\": \"web-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"web-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {\n          \"type\": \"Recreate\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"%CMD%\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"args\": [\n                  \"nodemon\",\n                  \"-L\",\n                  \"app/bin/www\"\n                ],\n                \"image\": \"centos/httpd\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 3000\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"mountPath\": \"/src/app\",\n                    \"name\": \"web-claim0\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": [\n              {\n                \"name\": \"web-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"web-claim0\"\n                }\n              }\n            ]\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/volumes-from/output-os-case.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"bar\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"cat\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"cat\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"headless\",\n            \"port\": 55555,\n            \"targetPort\": 0\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"clusterIP\": \"None\"\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"bar\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"bar:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"bar\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"bar\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim0\"\n                }\n              },\n              {\n                \"name\": \"bar-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"bar-claim1\"\n                }\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim1\"\n                }\n              },\n              {\n                \"name\": \"cat-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"cat-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"bar\",\n                \"image\": \" \",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"foo-claim0\",\n                    \"mountPath\": \"/foo1\"\n                  },\n                  {\n                    \"name\": \"bar-claim1\",\n                    \"mountPath\": \"/bar\"\n                  },\n                  {\n                    \"name\": \"foo-claim1\",\n                    \"mountPath\": \"/foo2\"\n                  },\n                  {\n                    \"name\": \"cat-claim0\",\n                    \"mountPath\": \"/cat\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"busybox\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"bar-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"bar-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"cat\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"cat\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"cat:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"cat\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"cat\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"cat-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"cat-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"cat\",\n                \"image\": \" \",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"cat-claim0\",\n                    \"mountPath\": \"/cat\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"cat\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"busybox\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"cat-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"cat-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"foo\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"foo:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"foo\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"foo\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"foo-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim0\"\n                }\n              },\n              {\n                \"name\": \"foo-claim1\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"foo-claim1\"\n                }\n              },\n              {\n                \"name\": \"cat-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"cat-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"foo\",\n                \"image\": \" \",\n                \"args\": [\n                  \"sleep\",\n                  \"3600\"\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"foo-claim0\",\n                    \"mountPath\": \"/foo1\"\n                  },\n                  {\n                    \"name\": \"foo-claim1\",\n                    \"mountPath\": \"/foo2\"\n                  },\n                  {\n                    \"name\": \"cat-claim0\",\n                    \"mountPath\": \"/cat\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"busybox\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"foo-claim1\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"foo-claim1\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/volumes-from/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"80\",\n            \"port\": 80,\n            \"targetPort\": 80\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"3030\",\n            \"port\": 3030,\n            \"targetPort\": 3000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"nginx\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"nginx:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"nginx\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"nginx\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"nginx-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"nginx-claim0\"\n                }\n              },\n              {\n                \"name\": \"web-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"web-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"nginx\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 80\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"nginx-claim0\",\n                    \"mountPath\": \"/www/public\"\n                  },\n                  {\n                    \"name\": \"web-claim0\",\n                    \"mountPath\": \"/src/app\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"nginx\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"nginx-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"nginx-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"%CMD%\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"type\": \"Recreate\",\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"volumes\": [\n              {\n                \"name\": \"web-claim0\",\n                \"persistentVolumeClaim\": {\n                  \"claimName\": \"web-claim0\"\n                }\n              }\n            ],\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"args\": [\n                  \"nodemon\",\n                  \"-L\",\n                  \"app/bin/www\"\n                ],\n                \"ports\": [\n                  {\n                    \"containerPort\": 3000\n                  }\n                ],\n                \"resources\": {},\n                \"volumeMounts\": [\n                  {\n                    \"name\": \"web-claim0\",\n                    \"mountPath\": \"/src/app\"\n                  }\n                ]\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"centos/httpd\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"PersistentVolumeClaim\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web-claim0\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web-claim0\"\n        }\n      },\n      \"spec\": {\n        \"accessModes\": [\n          \"ReadWriteOnce\"\n        ],\n        \"resources\": {\n          \"requests\": {\n            \"storage\": \"100Mi\"\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/windows/compose.yaml",
    "content": "services:\n  db:\n    image: nginx:latest\n    ports:\n      - \"80\"\n    volumes:\n      - C:\\Users\\data_sux:D:\\config:rw\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/windows/output-k8s.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: db\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: nginx:latest\n          name: db\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          volumeMounts:\n            - mountPath: D:\\config\n              name: db-claim0\n      restartPolicy: Always\n      volumes:\n        - name: db-claim0\n          persistentVolumeClaim:\n            claimName: db-claim0\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: db-claim0\n  name: db-claim0\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n"
  },
  {
    "path": "script/test/fixtures/volume-mounts/windows/output-os.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  ports:\n    - name: \"80\"\n      port: 80\n      targetPort: 80\n  selector:\n    io.kompose.service: db\n\n\n---\napiVersion: apps.openshift.io/v1\nkind: DeploymentConfig\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  replicas: 1\n  selector:\n    io.kompose.service: db\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        io.kompose.service: db\n    spec:\n      containers:\n        - image: ' '\n          name: db\n          ports:\n            - containerPort: 80\n              protocol: TCP\n          volumeMounts:\n            - mountPath: D:\\config\n              name: db-claim0\n      restartPolicy: Always\n      volumes:\n        - name: db-claim0\n          persistentVolumeClaim:\n            claimName: db-claim0\n  test: false\n  triggers:\n    - type: ConfigChange\n    - imageChangeParams:\n        automatic: true\n        containerNames:\n          - db\n        from:\n          kind: ImageStreamTag\n          name: db:latest\n      type: ImageChange\n\n---\napiVersion: image.openshift.io/v1\nkind: ImageStream\nmetadata:\n  labels:\n    io.kompose.service: db\n  name: db\nspec:\n  lookupPolicy:\n    local: false\n  tags:\n    - from:\n        kind: DockerImage\n        name: nginx:latest\n      name: latest\n      referencePolicy:\n        type: \"\"\n\n\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    io.kompose.service: db-claim0\n  name: db-claim0\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 100Mi\n\n\n"
  },
  {
    "path": "script/test/fixtures/yaml-and-yml/docker-compose.yaml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/yaml-and-yml/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"kompose convert --stdout -j\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"kompose convert --stdout -j\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/yaml-and-yml/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/yaml-and-yml/yml/docker-compose.yml",
    "content": "web:\n  image: tuna/docker-counter23\n  ports:\n    - \"5000:5000\"\n  links:\n    - redis\nredis:\n  image: redis:3.0\n  ports:\n    - \"6379\"\n"
  },
  {
    "path": "script/test/fixtures/yaml-and-yml/yml/output-k8s-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"name\": \"redis\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"redis\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"kompose convert --stdout -j\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"redis:3.0\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"redis\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"apiVersion\": \"apps/v1\",\n      \"kind\": \"Deployment\",\n      \"metadata\": {\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        },\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"name\": \"web\"\n      },\n      \"spec\": {\n        \"replicas\": 1,\n        \"selector\": {\n          \"matchLabels\": {\n            \"io.kompose.service\": \"web\"\n          }\n        },\n        \"strategy\": {},\n        \"template\": {\n          \"metadata\": {\n            \"annotations\": {\n              \"kompose.cmd\": \"kompose convert --stdout -j\",\n              \"kompose.version\": \"%VERSION%\"\n            },\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"image\": \"tuna/docker-counter23\",\n                \"imagePullPolicy\": \"\",\n                \"name\": \"web\",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\",\n            \"serviceAccountName\": \"\",\n            \"volumes\": null\n          }\n        }\n      },\n      \"status\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test/fixtures/yaml-and-yml/yml/output-os-template.json",
    "content": "{\n  \"kind\": \"List\",\n  \"apiVersion\": \"v1\",\n  \"metadata\": {},\n  \"items\": [\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"6379\",\n            \"port\": 6379,\n            \"targetPort\": 6379\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"Service\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"ports\": [\n          {\n            \"name\": \"5000\",\n            \"port\": 5000,\n            \"targetPort\": 5000\n          }\n        ],\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"status\": {\n        \"loadBalancer\": {}\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"redis\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"redis:3.0\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"redis\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"redis\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"redis\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 6379\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"redis\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"redis\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"3.0\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"redis:3.0\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    },\n    {\n      \"kind\": \"DeploymentConfig\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"annotations\": {\n          \"kompose.cmd\": \"kompose --provider=openshift convert --stdout -j\",\n          \"kompose.version\": \"%VERSION%\"\n        }\n      },\n      \"spec\": {\n        \"strategy\": {\n          \"resources\": {}\n        },\n        \"triggers\": [\n          {\n            \"type\": \"ConfigChange\"\n          },\n          {\n            \"type\": \"ImageChange\",\n            \"imageChangeParams\": {\n              \"automatic\": true,\n              \"containerNames\": [\n                \"web\"\n              ],\n              \"from\": {\n                \"kind\": \"ImageStreamTag\",\n                \"name\": \"web:latest\"\n              }\n            }\n          }\n        ],\n        \"replicas\": 1,\n        \"test\": false,\n        \"selector\": {\n          \"io.kompose.service\": \"web\"\n        },\n        \"template\": {\n          \"metadata\": {\n            \"creationTimestamp\": null,\n            \"labels\": {\n              \"io.kompose.service\": \"web\"\n            }\n          },\n          \"spec\": {\n            \"containers\": [\n              {\n                \"name\": \"web\",\n                \"image\": \" \",\n                \"ports\": [\n                  {\n                    \"containerPort\": 5000\n                  }\n                ],\n                \"resources\": {}\n              }\n            ],\n            \"restartPolicy\": \"Always\"\n          }\n        }\n      },\n      \"status\": {}\n    },\n    {\n      \"kind\": \"ImageStream\",\n      \"apiVersion\": \"v1\",\n      \"metadata\": {\n        \"name\": \"web\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n          \"io.kompose.service\": \"web\"\n        }\n      },\n      \"spec\": {\n        \"tags\": [\n          {\n            \"name\": \"latest\",\n            \"annotations\": null,\n            \"from\": {\n              \"kind\": \"DockerImage\",\n              \"name\": \"tuna/docker-counter23\"\n            },\n            \"generation\": null,\n            \"importPolicy\": {}\n          }\n        ]\n      },\n      \"status\": {\n        \"dockerImageRepository\": \"\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "script/test_in_container/Dockerfile",
    "content": "# Copyright 2016 The Kubernetes 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\n\n# This Dockefile creates image where all Kompose tests can be run\n\nFROM registry.centos.org/centos/centos:7\n\nRUN yum -y update && yum -y upgrade && \\\n    yum -y install epel-release && \\\n    yum -y install gcc make git jq && \\\n    yum -y clean all\n\nENV GOPATH=\"/opt/go\" \\\n    GOROOT=\"/usr/local/go\" \\\n    GOVERSION=\"1.15.4\" \\\n    # KOMPOSE_TMP_SRC is where kompose source will be mounted from host\n    KOMPOSE_TMP_SRC=\"/opt/tmp/kompose\" \n\nENV PATH=\"$PATH:$GOPATH/bin:$GOROOT/bin\" \\\n    # KOMPOSE_SRC is where kompose source will be copied when container starts (by run.sh script)\n    # this is to ensure that we won't write anything to host volume mount\n    KOMPOSE_SRC=\"$GOPATH/src/github.com/kubernetes/kompose\"\n\nWORKDIR /tmp/go\nRUN curl https://storage.googleapis.com/golang/go$GOVERSION.linux-amd64.tar.gz | tar -xz -C /usr/local\n\nWORKDIR $KOMPOSE_SRC\n# This image can be run as any user\nRUN chmod -R ugo+rw $GOPATH\n\nCOPY run.sh /opt/tools/\nENTRYPOINT [\"/opt/tools/run.sh\"]\n"
  },
  {
    "path": "script/test_in_container/run.sh",
    "content": "#!/bin/bash\n\nset -e\n\n# Copyright 2017 The Kubernetes 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\n\n# Container should be started with Kompose source mounted as read-only volume $KOMPOSE_TMP_SRC\n# Copy Kompose sources to another directory after container starts.\n# We can be sure that this container won't modify any files on hosts disk.\ncp -r $KOMPOSE_TMP_SRC/ $(dirname $KOMPOSE_SRC)\n\nmake test\n"
  }
]